[core] remove assert in fdevent_unregister()
[lighttpd.git] / src / fdevent.c
blob6d5096c8bc752fd88150a142a81f3b63e748018b
1 #include "first.h"
3 #include "base.h"
4 #include "log.h"
6 #include <sys/types.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <stdio.h>
13 #include <fcntl.h>
14 #include <assert.h>
17 fdevents *fdevent_init(server *srv, size_t maxfds, fdevent_handler_t type) {
18 fdevents *ev;
20 ev = calloc(1, sizeof(*ev));
21 force_assert(NULL != ev);
22 ev->srv = srv;
23 ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
24 force_assert(NULL != ev->fdarray);
25 ev->maxfds = maxfds;
27 switch(type) {
28 case FDEVENT_HANDLER_POLL:
29 if (0 != fdevent_poll_init(ev)) {
30 log_error_write(srv, __FILE__, __LINE__, "S",
31 "event-handler poll failed");
32 goto error;
34 return ev;
35 case FDEVENT_HANDLER_SELECT:
36 if (0 != fdevent_select_init(ev)) {
37 log_error_write(srv, __FILE__, __LINE__, "S",
38 "event-handler select failed");
39 goto error;
41 return ev;
42 case FDEVENT_HANDLER_LINUX_SYSEPOLL:
43 if (0 != fdevent_linux_sysepoll_init(ev)) {
44 log_error_write(srv, __FILE__, __LINE__, "S",
45 "event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"");
46 goto error;
48 return ev;
49 case FDEVENT_HANDLER_SOLARIS_DEVPOLL:
50 if (0 != fdevent_solaris_devpoll_init(ev)) {
51 log_error_write(srv, __FILE__, __LINE__, "S",
52 "event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"");
53 goto error;
55 return ev;
56 case FDEVENT_HANDLER_SOLARIS_PORT:
57 if (0 != fdevent_solaris_port_init(ev)) {
58 log_error_write(srv, __FILE__, __LINE__, "S",
59 "event-handler solaris-eventports failed, try to set server.event-handler = \"poll\" or \"select\"");
60 goto error;
62 return ev;
63 case FDEVENT_HANDLER_FREEBSD_KQUEUE:
64 if (0 != fdevent_freebsd_kqueue_init(ev)) {
65 log_error_write(srv, __FILE__, __LINE__, "S",
66 "event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"");
67 goto error;
69 return ev;
70 case FDEVENT_HANDLER_LIBEV:
71 if (0 != fdevent_libev_init(ev)) {
72 log_error_write(srv, __FILE__, __LINE__, "S",
73 "event-handler libev failed, try to set server.event-handler = \"poll\" or \"select\"");
74 goto error;
76 return ev;
77 case FDEVENT_HANDLER_UNSET:
78 break;
81 error:
82 free(ev->fdarray);
83 free(ev);
85 log_error_write(srv, __FILE__, __LINE__, "S",
86 "event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"");
87 return NULL;
90 void fdevent_free(fdevents *ev) {
91 size_t i;
92 if (!ev) return;
94 if (ev->free) ev->free(ev);
96 for (i = 0; i < ev->maxfds; i++) {
97 if (ev->fdarray[i]) free(ev->fdarray[i]);
100 free(ev->fdarray);
101 free(ev);
104 int fdevent_reset(fdevents *ev) {
105 if (ev->reset) return ev->reset(ev);
107 return 0;
110 static fdnode *fdnode_init(void) {
111 fdnode *fdn;
113 fdn = calloc(1, sizeof(*fdn));
114 force_assert(NULL != fdn);
115 fdn->fd = -1;
116 return fdn;
119 static void fdnode_free(fdnode *fdn) {
120 free(fdn);
123 int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
124 fdnode *fdn;
126 fdn = fdnode_init();
127 fdn->handler = handler;
128 fdn->fd = fd;
129 fdn->ctx = ctx;
130 fdn->handler_ctx = NULL;
131 fdn->events = 0;
133 ev->fdarray[fd] = fdn;
135 return 0;
138 int fdevent_unregister(fdevents *ev, int fd) {
139 fdnode *fdn;
141 if (!ev) return 0;
142 fdn = ev->fdarray[fd];
144 fdnode_free(fdn);
146 ev->fdarray[fd] = NULL;
148 return 0;
151 void fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
152 if (-1 == fd) return;
153 if (NULL == ev->fdarray[fd]) return;
155 if (ev->event_del) *fde_ndx = ev->event_del(ev, *fde_ndx, fd);
156 ev->fdarray[fd]->events = 0;
159 void fdevent_event_set(fdevents *ev, int *fde_ndx, int fd, int events) {
160 if (-1 == fd) return;
162 /*(Note: skips registering with kernel if initial events is 0,
163 * so caller should pass non-zero events for initial registration.
164 * If never registered due to never being called with non-zero events,
165 * then FDEVENT_HUP or FDEVENT_ERR will never be returned.) */
166 if (ev->fdarray[fd]->events == events) return;/*(no change; nothing to do)*/
168 if (ev->event_set) *fde_ndx = ev->event_set(ev, *fde_ndx, fd, events);
169 ev->fdarray[fd]->events = events;
172 void fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int event) {
173 int events;
174 if (-1 == fd) return;
176 events = ev->fdarray[fd]->events;
177 if ((events & event) || 0 == event) return; /*(no change; nothing to do)*/
179 events |= event;
180 if (ev->event_set) *fde_ndx = ev->event_set(ev, *fde_ndx, fd, events);
181 ev->fdarray[fd]->events = events;
184 void fdevent_event_clr(fdevents *ev, int *fde_ndx, int fd, int event) {
185 int events;
186 if (-1 == fd) return;
188 events = ev->fdarray[fd]->events;
189 if (!(events & event)) return; /*(no change; nothing to do)*/
191 events &= ~event;
192 if (ev->event_set) *fde_ndx = ev->event_set(ev, *fde_ndx, fd, events);
193 ev->fdarray[fd]->events = events;
196 int fdevent_poll(fdevents *ev, int timeout_ms) {
197 if (ev->poll == NULL) SEGFAULT();
198 return ev->poll(ev, timeout_ms);
201 int fdevent_event_get_revent(fdevents *ev, size_t ndx) {
202 if (ev->event_get_revent == NULL) SEGFAULT();
204 return ev->event_get_revent(ev, ndx);
207 int fdevent_event_get_fd(fdevents *ev, size_t ndx) {
208 if (ev->event_get_fd == NULL) SEGFAULT();
210 return ev->event_get_fd(ev, ndx);
213 fdevent_handler fdevent_get_handler(fdevents *ev, int fd) {
214 if (ev->fdarray[fd] == NULL) SEGFAULT();
215 if (ev->fdarray[fd]->fd != fd) SEGFAULT();
217 return ev->fdarray[fd]->handler;
220 void * fdevent_get_context(fdevents *ev, int fd) {
221 if (ev->fdarray[fd] == NULL) SEGFAULT();
222 if (ev->fdarray[fd]->fd != fd) SEGFAULT();
224 return ev->fdarray[fd]->ctx;
227 void fd_close_on_exec(int fd) {
228 #ifdef FD_CLOEXEC
229 if (fd < 0) return;
230 force_assert(-1 != fcntl(fd, F_SETFD, FD_CLOEXEC));
231 #else
232 UNUSED(fd);
233 #endif
236 int fdevent_fcntl_set(fdevents *ev, int fd) {
237 fd_close_on_exec(fd);
238 if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd);
239 #ifdef O_NONBLOCK
240 return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
241 #else
242 return 0;
243 #endif
247 int fdevent_event_next_fdndx(fdevents *ev, int ndx) {
248 if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx);
250 return -1;