[mod_cgi] fix pipe_cloexec() when no O_CLOEXEC
[lighttpd.git] / src / fdevent_linux_sysepoll.c
blob391833d4b60c54234c6501286637871828fefb92
1 #include "first.h"
3 #include "fdevent.h"
4 #include "buffer.h"
5 #include "log.h"
7 #include <sys/types.h>
9 #include <unistd.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <signal.h>
15 #include <fcntl.h>
17 #ifdef USE_LINUX_EPOLL
19 # include <sys/epoll.h>
21 static void fdevent_linux_sysepoll_free(fdevents *ev) {
22 close(ev->epoll_fd);
23 free(ev->epoll_events);
26 static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) {
27 struct epoll_event ep;
29 if (fde_ndx < 0) return -1;
31 memset(&ep, 0, sizeof(ep));
33 ep.data.fd = fd;
34 ep.data.ptr = NULL;
36 if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) {
37 log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
38 "epoll_ctl failed: ", strerror(errno), ", dying");
40 SEGFAULT();
42 return 0;
46 return -1;
49 static int fdevent_linux_sysepoll_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
50 struct epoll_event ep;
51 int add = 0;
53 if (fde_ndx == -1) add = 1;
55 memset(&ep, 0, sizeof(ep));
57 ep.events = 0;
59 if (events & FDEVENT_IN) ep.events |= EPOLLIN;
60 if (events & FDEVENT_OUT) ep.events |= EPOLLOUT;
62 /**
64 * with EPOLLET we don't get a FDEVENT_HUP
65 * if the close is delay after everything has
66 * sent.
70 ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */;
72 ep.data.ptr = NULL;
73 ep.data.fd = fd;
75 if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) {
76 log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
77 "epoll_ctl failed: ", strerror(errno), ", dying");
79 SEGFAULT();
81 return 0;
84 return fd;
87 static int fdevent_linux_sysepoll_poll(fdevents *ev, int timeout_ms) {
88 return epoll_wait(ev->epoll_fd, ev->epoll_events, ev->maxfds, timeout_ms);
91 static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) {
92 int events = 0, e;
94 e = ev->epoll_events[ndx].events;
95 if (e & EPOLLIN) events |= FDEVENT_IN;
96 if (e & EPOLLOUT) events |= FDEVENT_OUT;
97 if (e & EPOLLERR) events |= FDEVENT_ERR;
98 if (e & EPOLLHUP) events |= FDEVENT_HUP;
99 if (e & EPOLLPRI) events |= FDEVENT_PRI;
101 return events;
104 static int fdevent_linux_sysepoll_event_get_fd(fdevents *ev, size_t ndx) {
105 # if 0
106 log_error_write(ev->srv, __FILE__, __LINE__, "SD, D",
107 "fdevent_linux_sysepoll_event_get_fd: ", (int) ndx, ev->epoll_events[ndx].data.fd);
108 # endif
110 return ev->epoll_events[ndx].data.fd;
113 static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) {
114 size_t i;
116 UNUSED(ev);
118 i = (ndx < 0) ? 0 : ndx + 1;
120 return i;
123 int fdevent_linux_sysepoll_init(fdevents *ev) {
124 ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
125 #define SET(x) \
126 ev->x = fdevent_linux_sysepoll_##x;
128 SET(free);
129 SET(poll);
131 SET(event_del);
132 SET(event_set);
134 SET(event_next_fdndx);
135 SET(event_get_fd);
136 SET(event_get_revent);
138 if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) {
139 log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
140 "epoll_create failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\"");
142 return -1;
145 fd_close_on_exec(ev->epoll_fd);
147 ev->epoll_events = malloc(ev->maxfds * sizeof(*ev->epoll_events));
148 force_assert(NULL != ev->epoll_events);
150 return 0;
153 #else
154 int fdevent_linux_sysepoll_init(fdevents *ev) {
155 UNUSED(ev);
157 log_error_write(ev->srv, __FILE__, __LINE__, "S",
158 "linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"");
160 return -1;
162 #endif