[core] set REDIRECT_STATUS to error_handler_saved_status (fixes #1828)
[lighttpd.git] / src / fdevent_libev.c
blobb0a4f77f6670616d904e342f365f453c664df210
1 #include "first.h"
3 #include "fdevent.h"
4 #include "buffer.h"
5 #include "log.h"
7 #include <assert.h>
9 #ifdef USE_LIBEV
11 # include <ev.h>
13 static void io_watcher_cb(struct ev_loop *loop, ev_io *w, int revents) {
14 fdevents *ev = w->data;
15 fdnode *fdn = ev->fdarray[w->fd];
16 int r = 0;
17 UNUSED(loop);
19 if (revents & EV_READ) r |= FDEVENT_IN;
20 if (revents & EV_WRITE) r |= FDEVENT_OUT;
21 if (revents & EV_ERROR) r |= FDEVENT_ERR;
23 switch (r = (*fdn->handler)(ev->srv, fdn->ctx, r)) {
24 case HANDLER_FINISHED:
25 case HANDLER_GO_ON:
26 case HANDLER_WAIT_FOR_EVENT:
27 case HANDLER_WAIT_FOR_FD:
28 break;
29 case HANDLER_ERROR:
30 /* should never happen */
31 SEGFAULT();
32 break;
33 default:
34 log_error_write(ev->srv, __FILE__, __LINE__, "d", r);
35 break;
39 static void fdevent_libev_free(fdevents *ev) {
40 UNUSED(ev);
43 static int fdevent_libev_event_del(fdevents *ev, int fde_ndx, int fd) {
44 fdnode *fdn;
45 ev_io *watcher;
47 if (-1 == fde_ndx) return -1;
49 fdn = ev->fdarray[fd];
50 watcher = fdn->handler_ctx;
52 if (!watcher) return -1;
54 ev_io_stop(ev->libev_loop, watcher);
55 free(watcher);
56 fdn->handler_ctx = NULL;
58 return -1;
61 static int fdevent_libev_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
62 fdnode *fdn = ev->fdarray[fd];
63 ev_io *watcher = fdn->handler_ctx;
64 int ev_events = 0;
65 UNUSED(fde_ndx);
67 if (events & FDEVENT_IN) ev_events |= EV_READ;
68 if (events & FDEVENT_OUT) ev_events |= EV_WRITE;
70 if (!watcher) {
71 fdn->handler_ctx = watcher = calloc(1, sizeof(ev_io));
72 force_assert(watcher);
74 ev_io_init(watcher, io_watcher_cb, fd, ev_events);
75 watcher->data = ev;
76 ev_io_start(ev->libev_loop, watcher);
77 } else {
78 if ((watcher->events & (EV_READ | EV_WRITE)) != ev_events) {
79 ev_io_stop(ev->libev_loop, watcher);
80 ev_io_set(watcher, watcher->fd, ev_events);
81 ev_io_start(ev->libev_loop, watcher);
85 return fd;
88 static void timeout_watcher_cb(struct ev_loop *loop, ev_timer *w, int revents) {
89 UNUSED(loop);
90 UNUSED(w);
91 UNUSED(revents);
93 ev_timer_stop(loop, w);
97 static int fdevent_libev_poll(fdevents *ev, int timeout_ms) {
98 union {
99 struct ev_watcher w;
100 struct ev_timer timer;
101 } timeout_watcher;
103 if (!timeout_ms) timeout_ms = 1;
105 ev_init(&timeout_watcher.w, NULL);
106 ev_set_cb(&timeout_watcher.timer, timeout_watcher_cb);
107 timeout_watcher.timer.repeat = ((ev_tstamp) timeout_ms)/1000.0;
108 force_assert(timeout_watcher.timer.repeat);
109 ev_timer_again(ev->libev_loop, &timeout_watcher.timer);
111 ev_loop(ev->libev_loop, EVLOOP_ONESHOT);
113 ev_timer_stop(ev->libev_loop, &timeout_watcher.timer);
115 return 0;
118 static int fdevent_libev_event_get_revent(fdevents *ev, size_t ndx) {
119 UNUSED(ev);
120 UNUSED(ndx);
122 return 0;
125 static int fdevent_libev_event_get_fd(fdevents *ev, size_t ndx) {
126 UNUSED(ev);
127 UNUSED(ndx);
129 return -1;
132 static int fdevent_libev_event_next_fdndx(fdevents *ev, int ndx) {
133 UNUSED(ev);
134 UNUSED(ndx);
136 return -1;
139 static int fdevent_libev_reset(fdevents *ev) {
140 UNUSED(ev);
142 ev_default_fork();
144 return 0;
147 int fdevent_libev_init(fdevents *ev) {
148 ev->type = FDEVENT_HANDLER_LIBEV;
149 #define SET(x) \
150 ev->x = fdevent_libev_##x;
152 SET(free);
153 SET(poll);
154 SET(reset);
156 SET(event_del);
157 SET(event_set);
159 SET(event_next_fdndx);
160 SET(event_get_fd);
161 SET(event_get_revent);
163 if (NULL == (ev->libev_loop = ev_default_loop(0))) {
164 log_error_write(ev->srv, __FILE__, __LINE__, "S",
165 "ev_default_loop failed , try to set server.event-handler = \"poll\" or \"select\"");
167 return -1;
170 return 0;
173 #else
174 int fdevent_libev_init(fdevents *ev) {
175 UNUSED(ev);
177 log_error_write(ev->srv, __FILE__, __LINE__, "S",
178 "libev not supported, try to set server.event-handler = \"poll\" or \"select\"");
180 return -1;
182 #endif