-
Notifications
You must be signed in to change notification settings - Fork 18
/
module-shm-preload.c
137 lines (111 loc) · 3.63 KB
/
module-shm-preload.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
* module-shm-preload.c
*
* Created on: Nov 9, 2016
* Author: Edgars
*/
/* Rewriting a few system functions to avoid duplicating a fluid Redis code.
* I know this isn't pretty, but it's the next cleanest thing besides forking Redis.
* Asking users to compile a custom Redis is not nice. The whole point of modules
* is to avoid such weirdities.
*/
#include "config.h"
#include <dlfcn.h>
#include <stddef.h>
#ifdef HAVE_EVPORT
#include <port.h>
#endif
#ifdef HAVE_EPOLL
#include <sys/epoll.h>
#endif
#ifdef HAVE_KQUEUE
#include <sys/event.h>
#endif
#include <sys/select.h>
void (*ModuleSHM_BeforeSelect)();
void (*ModuleSHM_AfterSelect)();
ssize_t (*ModuleSHM_ReadUnusual)(int fd, void *buf, size_t count);
ssize_t (*ModuleSHM_WriteUnusual)(int fd, const void *buf, size_t count);
#ifdef HAVE_EVPORT
int port_getn(int port, port_event_t list[], uint_t max,
uint_t *nget, const timespec_t *timeout)
{
static int (*real_port_getn)(int epfd, struct epoll_event *events,
int maxevents, int timeout) = NULL;
if (real_port_getn == NULL) {
real_port_getn = dlsym(RTLD_NEXT, "port_getn");
}
ModuleSHM_BeforeSelect();
int res = real_port_getn(port, list, max, nget, timeout);
ModuleSHM_AfterSelect();
return res;
}
#endif
#ifdef HAVE_EPOLL
int epoll_wait(int epfd, struct epoll_event *events,
int maxevents, int timeout)
{
static int (*real_epoll_wait)(int epfd, struct epoll_event *events,
int maxevents, int timeout) = NULL;
if (real_epoll_wait == NULL) {
real_epoll_wait = dlsym(RTLD_NEXT, "epoll_wait");
}
ModuleSHM_BeforeSelect();
int res = real_epoll_wait(epfd, events, maxevents, timeout);
ModuleSHM_AfterSelect();
return res;
}
#endif
#ifdef HAVE_KQUEUE
int kevent(int kq, const struct kevent *changelist, int nchanges,
struct kevent *eventlist, int nevents, const struct timespec *timeout)
{
static int (*real_kevent)(int kq, const struct kevent *changelist,
int nchanges, struct kevent *eventlist, int nevents,
const struct timespec *timeout) = NULL;
if (real_kevent == NULL) {
real_kevent = dlsym(RTLD_NEXT, "kevent");
}
ModuleSHM_BeforeSelect();
int res = real_kevent(kq, changelist, nchanges, eventlist, nevents, timeout);
ModuleSHM_AfterSelect();
return res;
}
#endif
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout)
{
static int (*real_select)(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout) = NULL;
if (real_select == NULL) {
real_select = dlsym(RTLD_NEXT, "select");
}
ModuleSHM_BeforeSelect();
int res = real_select(nfds, readfds, writefds, exceptfds, timeout);
ModuleSHM_AfterSelect();
return res;
}
ssize_t read(int fd, void *buf, size_t count)
{
static int (*real_read)(int fd, void *buf, size_t count) = NULL;
if (real_read == NULL) {
real_read = dlsym(RTLD_NEXT, "read");
}
if (fd == -1) {
return ModuleSHM_ReadUnusual(fd, buf, count);
} else {
return real_read(fd, buf, count);
}
}
ssize_t write(int fd, const void *buf, size_t count)
{
static int (*real_write)(int fd, const void *buf, size_t count) = NULL;
if (real_write == NULL) {
real_write = dlsym(RTLD_NEXT, "write");
}
if (fd == -1) {
return ModuleSHM_WriteUnusual(fd, buf, count);
} else {
return real_write(fd, buf, count);
}
}