[mod_cgi] fix pipe_cloexec() when no O_CLOEXEC
[lighttpd.git] / src / fdevent_poll.c
blobdf7da5993bced34877c19a7e08b1b9c6beddc61e
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_POLL
19 # ifdef HAVE_POLL_H
20 # include <poll.h>
21 # else
22 # include <sys/poll.h>
23 # endif
25 static void fdevent_poll_free(fdevents *ev) {
26 free(ev->pollfds);
27 if (ev->unused.ptr) free(ev->unused.ptr);
30 static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) {
31 if (fde_ndx < 0) return -1;
33 if ((size_t)fde_ndx >= ev->used) {
34 log_error_write(ev->srv, __FILE__, __LINE__, "SdD",
35 "del! out of range ", fde_ndx, (int) ev->used);
36 SEGFAULT();
39 if (ev->pollfds[fde_ndx].fd == fd) {
40 size_t k = fde_ndx;
42 ev->pollfds[k].fd = -1;
43 /* ev->pollfds[k].events = 0; */
44 /* ev->pollfds[k].revents = 0; */
46 if (ev->unused.size == 0) {
47 ev->unused.size = 16;
48 ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
49 force_assert(NULL != ev->unused.ptr);
50 } else if (ev->unused.size == ev->unused.used) {
51 ev->unused.size += 16;
52 ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
53 force_assert(NULL != ev->unused.ptr);
56 ev->unused.ptr[ev->unused.used++] = k;
57 } else {
58 log_error_write(ev->srv, __FILE__, __LINE__, "SdD",
59 "del! ", ev->pollfds[fde_ndx].fd, fd);
61 SEGFAULT();
64 return -1;
67 #if 0
68 static int fdevent_poll_event_compress(fdevents *ev) {
69 size_t j;
71 if (ev->used == 0) return 0;
72 if (ev->unused.used != 0) return 0;
74 for (j = ev->used - 1; j + 1 > 0 && ev->pollfds[j].fd == -1; j--) ev->used--;
76 return 0;
78 #endif
80 static int fdevent_poll_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
81 int pevents = 0;
82 if (events & FDEVENT_IN) pevents |= POLLIN;
83 if (events & FDEVENT_OUT) pevents |= POLLOUT;
85 /* known index */
87 if (fde_ndx != -1) {
88 if (ev->pollfds[fde_ndx].fd == fd) {
89 ev->pollfds[fde_ndx].events = pevents;
91 return fde_ndx;
93 log_error_write(ev->srv, __FILE__, __LINE__, "SdD",
94 "set: ", fde_ndx, ev->pollfds[fde_ndx].fd);
95 SEGFAULT();
98 if (ev->unused.used > 0) {
99 int k = ev->unused.ptr[--ev->unused.used];
101 ev->pollfds[k].fd = fd;
102 ev->pollfds[k].events = pevents;
104 return k;
105 } else {
106 if (ev->size == 0) {
107 ev->size = 16;
108 ev->pollfds = malloc(sizeof(*ev->pollfds) * ev->size);
109 force_assert(NULL != ev->pollfds);
110 } else if (ev->size == ev->used) {
111 ev->size += 16;
112 ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
113 force_assert(NULL != ev->pollfds);
116 ev->pollfds[ev->used].fd = fd;
117 ev->pollfds[ev->used].events = pevents;
119 return ev->used++;
123 static int fdevent_poll_poll(fdevents *ev, int timeout_ms) {
124 #if 0
125 fdevent_poll_event_compress(ev);
126 #endif
127 return poll(ev->pollfds, ev->used, timeout_ms);
130 static int fdevent_poll_event_get_revent(fdevents *ev, size_t ndx) {
131 int r, poll_r;
133 if (ndx >= ev->used) {
134 log_error_write(ev->srv, __FILE__, __LINE__, "sii",
135 "dying because: event: ", (int) ndx, (int) ev->used);
137 SEGFAULT();
139 return 0;
142 if (ev->pollfds[ndx].revents & POLLNVAL) {
143 /* should never happen */
144 SEGFAULT();
147 r = 0;
148 poll_r = ev->pollfds[ndx].revents;
150 /* map POLL* to FDEVEN_*; they are probably the same, but still. */
152 if (poll_r & POLLIN) r |= FDEVENT_IN;
153 if (poll_r & POLLOUT) r |= FDEVENT_OUT;
154 if (poll_r & POLLERR) r |= FDEVENT_ERR;
155 if (poll_r & POLLHUP) r |= FDEVENT_HUP;
156 if (poll_r & POLLNVAL) r |= FDEVENT_NVAL;
157 if (poll_r & POLLPRI) r |= FDEVENT_PRI;
159 return r;
162 static int fdevent_poll_event_get_fd(fdevents *ev, size_t ndx) {
163 return ev->pollfds[ndx].fd;
166 static int fdevent_poll_event_next_fdndx(fdevents *ev, int ndx) {
167 size_t i;
169 i = (ndx < 0) ? 0 : ndx + 1;
170 for (; i < ev->used; i++) {
171 if (ev->pollfds[i].revents) return i;
174 return -1;
177 int fdevent_poll_init(fdevents *ev) {
178 ev->type = FDEVENT_HANDLER_POLL;
179 #define SET(x) \
180 ev->x = fdevent_poll_##x;
182 SET(free);
183 SET(poll);
185 SET(event_del);
186 SET(event_set);
188 SET(event_next_fdndx);
189 SET(event_get_fd);
190 SET(event_get_revent);
192 return 0;
198 #else
199 int fdevent_poll_init(fdevents *ev) {
200 UNUSED(ev);
202 log_error_write(ev->srv, __FILE__, __LINE__,
203 "s", "poll is not supported, try to set server.event-handler = \"select\"");
205 return -1;
207 #endif