xref: /lighttpd1.4/src/fdevent.c (revision e11f72b1)
1 #include "first.h"
2 
3 #include "fdevent_impl.h"
4 #include "fdevent.h"
5 #include "buffer.h"
6 #include "log.h"
7 
8 #include <sys/types.h>
9 #include <sys/wait.h>
10 #include "sys-socket.h"
11 
12 #include <unistd.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <errno.h>
16 #include <fcntl.h>
17 #include <time.h>
18 
19 #ifdef SOCK_CLOEXEC
20 static int use_sock_cloexec;
21 #endif
22 #ifdef SOCK_NONBLOCK
23 static int use_sock_nonblock;
24 #endif
25 
26 int fdevent_config(const char **event_handler_name, log_error_st *errh) {
27 	static const struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
28 	{
29 		/* - epoll is most reliable
30 		 * - select works everywhere
31 		 */
32 #ifdef FDEVENT_USE_LINUX_EPOLL
33 		{ FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll" },
34 		{ FDEVENT_HANDLER_LINUX_SYSEPOLL, "epoll" },
35 #endif
36 #ifdef FDEVENT_USE_SOLARIS_PORT
37 		{ FDEVENT_HANDLER_SOLARIS_PORT,   "solaris-eventports" },
38 #endif
39 #ifdef FDEVENT_USE_SOLARIS_DEVPOLL
40 		{ FDEVENT_HANDLER_SOLARIS_DEVPOLL,"solaris-devpoll" },
41 #endif
42 #ifdef FDEVENT_USE_FREEBSD_KQUEUE
43 		{ FDEVENT_HANDLER_FREEBSD_KQUEUE, "freebsd-kqueue" },
44 		{ FDEVENT_HANDLER_FREEBSD_KQUEUE, "kqueue" },
45 #endif
46 #ifdef FDEVENT_USE_POLL
47 		{ FDEVENT_HANDLER_POLL,           "poll" },
48 #endif
49 #ifdef FDEVENT_USE_SELECT
50 		{ FDEVENT_HANDLER_SELECT,         "select" },
51 #endif
52 #ifdef FDEVENT_USE_LIBEV
53 		{ FDEVENT_HANDLER_LIBEV,          "libev" },
54 #endif
55 		{ FDEVENT_HANDLER_UNSET,          NULL }
56 	};
57 
58 	const char * event_handler = *event_handler_name;
59 	fdevent_handler_t et = FDEVENT_HANDLER_UNSET;
60 
61 	if (NULL == event_handler) {
62 		/* choose a good default
63 		 *
64 		 * the event_handler list is sorted by 'goodness'
65 		 * taking the first available should be the best solution
66 		 */
67 		et = event_handlers[0].et;
68 		*event_handler_name = event_handlers[0].name;
69 
70 		if (FDEVENT_HANDLER_UNSET == et) {
71 			log_error(errh, __FILE__, __LINE__,
72 			  "sorry, there is no event handler for this system");
73 
74 			return -1;
75 		}
76 	} else {
77 		/*
78 		 * User override
79 		 */
80 
81 		for (uint32_t i = 0; event_handlers[i].name; ++i) {
82 			if (0 == strcmp(event_handlers[i].name, event_handler)) {
83 				et = event_handlers[i].et;
84 				break;
85 			}
86 		}
87 
88 		if (FDEVENT_HANDLER_UNSET == et) {
89 			log_error(errh, __FILE__, __LINE__,
90 			  "the selected event-handler in unknown or not supported: %s",
91 			  event_handler);
92 			return -1;
93 		}
94 	}
95 
96 	return et;
97 }
98 
99 const char * fdevent_show_event_handlers(void) {
100     return
101       "\nEvent Handlers:\n\n"
102 #ifdef FDEVENT_USE_SELECT
103       "\t+ select (generic)\n"
104 #else
105       "\t- select (generic)\n"
106 #endif
107 #ifdef FDEVENT_USE_POLL
108       "\t+ poll (Unix)\n"
109 #else
110       "\t- poll (Unix)\n"
111 #endif
112 #ifdef FDEVENT_USE_LINUX_EPOLL
113       "\t+ epoll (Linux)\n"
114 #else
115       "\t- epoll (Linux)\n"
116 #endif
117 #ifdef FDEVENT_USE_SOLARIS_DEVPOLL
118       "\t+ /dev/poll (Solaris)\n"
119 #else
120       "\t- /dev/poll (Solaris)\n"
121 #endif
122 #ifdef FDEVENT_USE_SOLARIS_PORT
123       "\t+ eventports (Solaris)\n"
124 #else
125       "\t- eventports (Solaris)\n"
126 #endif
127 #ifdef FDEVENT_USE_FREEBSD_KQUEUE
128       "\t+ kqueue (FreeBSD)\n"
129 #else
130       "\t- kqueue (FreeBSD)\n"
131 #endif
132 #ifdef FDEVENT_USE_LIBEV
133       "\t+ libev (generic)\n"
134 #else
135       "\t- libev (generic)\n"
136 #endif
137       ;
138 }
139 
140 fdevents * fdevent_init(const char *event_handler, int *max_fds, int *cur_fds, log_error_st *errh) {
141 	fdevents *ev;
142 	uint32_t maxfds = (0 != *max_fds)
143 	  ? (uint32_t)*max_fds
144 	  : 4096;
145 	int type = fdevent_config(&event_handler, errh);
146 	if (type <= 0) return NULL;
147 
148       #ifdef SOCK_CLOEXEC
149 	/* Test if SOCK_CLOEXEC is supported by kernel.
150 	 * Linux kernels < 2.6.27 might return EINVAL if SOCK_CLOEXEC used
151 	 * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=529929
152 	 * http://www.linksysinfo.org/index.php?threads/lighttpd-no-longer-starts-toastman-1-28-0510-7.73132/
153 	 * Test if SOCK_NONBLOCK is ignored by kernel on sockets.
154 	 * (reported on Android running a custom ROM)
155 	 * https://redmine.lighttpd.net/issues/2883
156 	 */
157        #ifdef SOCK_NONBLOCK
158 	int fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
159        #else
160 	int fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
161        #endif
162 	if (fd >= 0) {
163 		int flags = fcntl(fd, F_GETFL, 0);
164               #ifdef SOCK_NONBLOCK
165 		use_sock_nonblock = (-1 != flags && (flags & O_NONBLOCK));
166               #endif
167 		use_sock_cloexec = 1;
168 		close(fd);
169 	}
170       #endif
171 
172       #ifdef FDEVENT_USE_SELECT
173 	/* select limits itself
174 	 * as it is a hard limit and will lead to a segfault we add some safety
175 	 * */
176 	if (type == FDEVENT_HANDLER_SELECT) {
177 		if (maxfds > (uint32_t)FD_SETSIZE - 200)
178 		    maxfds = (uint32_t)FD_SETSIZE - 200;
179 	}
180       #endif
181 	*max_fds = (int)maxfds;
182 	++maxfds; /*(+1 for event-handler fd)*/
183 
184 	ev = calloc(1, sizeof(*ev));
185 	force_assert(NULL != ev);
186 	ev->errh = errh;
187 	ev->cur_fds = cur_fds;
188 	ev->event_handler = event_handler;
189 	ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
190 	if (NULL == ev->fdarray) {
191 		log_error(ev->errh, __FILE__, __LINE__,
192 		  "server.max-fds too large? (%u)", maxfds-1);
193 		free(ev);
194 		return NULL;
195 	}
196 	ev->maxfds = maxfds;
197 
198 	switch(type) {
199 	#ifdef FDEVENT_USE_POLL
200 	case FDEVENT_HANDLER_POLL:
201 		if (0 == fdevent_poll_init(ev)) return ev;
202 		break;
203 	#endif
204 	#ifdef FDEVENT_USE_SELECT
205 	case FDEVENT_HANDLER_SELECT:
206 		if (0 == fdevent_select_init(ev)) return ev;
207 		break;
208 	#endif
209 	#ifdef FDEVENT_USE_LINUX_EPOLL
210 	case FDEVENT_HANDLER_LINUX_SYSEPOLL:
211 		if (0 == fdevent_linux_sysepoll_init(ev)) return ev;
212 		break;
213 	#endif
214 	#ifdef FDEVENT_USE_SOLARIS_DEVPOLL
215 	case FDEVENT_HANDLER_SOLARIS_DEVPOLL:
216 		if (0 == fdevent_solaris_devpoll_init(ev)) return ev;
217 		break;
218 	#endif
219 	#ifdef FDEVENT_USE_SOLARIS_PORT
220 	case FDEVENT_HANDLER_SOLARIS_PORT:
221 		if (0 == fdevent_solaris_port_init(ev)) return ev;
222 		break;
223 	#endif
224 	#ifdef FDEVENT_USE_FREEBSD_KQUEUE
225 	case FDEVENT_HANDLER_FREEBSD_KQUEUE:
226 		if (0 == fdevent_freebsd_kqueue_init(ev)) return ev;
227 		break;
228 	#endif
229 	#ifdef FDEVENT_USE_LIBEV
230 	case FDEVENT_HANDLER_LIBEV:
231 		if (0 == fdevent_libev_init(ev)) return ev;
232 		break;
233 	#endif
234 	case FDEVENT_HANDLER_UNSET:
235 	default:
236 		break;
237 	}
238 
239 	free(ev->fdarray);
240 	free(ev);
241 
242 	log_error(errh, __FILE__, __LINE__,
243 	  "event-handler failed: %s; "
244 	  "try to set server.event-handler = \"poll\" or \"select\"",
245 	  event_handler);
246 	return NULL;
247 }
248 
249 void fdevent_free(fdevents *ev) {
250 	if (!ev) return;
251 
252 	if (ev->free) ev->free(ev);
253 
254 	for (uint32_t i = 0; i < ev->maxfds; ++i) {
255 		/* (fdevent_sched_run() should already have been run,
256 		 *  but take reasonable precautions anyway) */
257 		if (ev->fdarray[i])
258 			free((fdnode *)((uintptr_t)ev->fdarray[i] & ~0x3));
259 	}
260 
261 	free(ev->fdarray);
262 	free(ev);
263 }
264 
265 int fdevent_reset(fdevents *ev) {
266 	int rc = (NULL != ev->reset) ? ev->reset(ev) : 0;
267 	if (-1 == rc) {
268 		log_error(ev->errh, __FILE__, __LINE__,
269 		  "event-handler failed: %s; "
270 		  "try to set server.event-handler = \"poll\" or \"select\"",
271 		  ev->event_handler ? ev->event_handler : "");
272 	}
273 	return rc;
274 }
275 
276 static fdnode *fdnode_init(void) {
277 	return calloc(1, sizeof(fdnode));
278 }
279 
280 static void fdnode_free(fdnode *fdn) {
281 	free(fdn);
282 }
283 
284 fdnode * fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
285 	fdnode *fdn  = ev->fdarray[fd] = fdnode_init();
286 	force_assert(NULL != fdn);
287 	fdn->handler = handler;
288 	fdn->fd      = fd;
289 	fdn->ctx     = ctx;
290 	fdn->events  = 0;
291 	fdn->fde_ndx = -1;
292       #ifdef FDEVENT_USE_LIBEV
293 	fdn->handler_ctx = NULL;
294       #endif
295 	return fdn;
296 }
297 
298 void fdevent_unregister(fdevents *ev, int fd) {
299 	fdnode *fdn = ev->fdarray[fd];
300 	if ((uintptr_t)fdn & 0x3) return; /*(should not happen)*/
301 	ev->fdarray[fd] = NULL;
302 	fdnode_free(fdn);
303 }
304 
305 void fdevent_sched_close(fdevents *ev, int fd, int issock) {
306 	fdnode *fdn = ev->fdarray[fd];
307 	if ((uintptr_t)fdn & 0x3) return;
308 	ev->fdarray[fd] = (fdnode *)((uintptr_t)fdn | (issock ? 0x1 : 0x2));
309 	fdn->handler = (fdevent_handler)NULL;
310 	fdn->ctx = ev->pendclose;
311 	ev->pendclose = fdn;
312 }
313 
314 static void fdevent_sched_run(fdevents *ev) {
315 	for (fdnode *fdn = ev->pendclose; fdn; ) {
316 		int fd, rc;
317 		fdnode *fdn_tmp;
318 	      #ifdef _WIN32
319 		rc = (uintptr_t)fdn & 0x3;
320 	      #endif
321 		fdn = (fdnode *)((uintptr_t)fdn & ~0x3);
322 		fd = fdn->fd;
323 	      #ifdef _WIN32
324 		if (rc == 0x1) {
325 			rc = closesocket(fd);
326 		}
327 		else if (rc == 0x2) {
328 			rc = close(fd);
329 		}
330 	      #else
331 		rc = close(fd);
332 	      #endif
333 
334 		if (0 != rc) {
335 			log_perror(ev->errh, __FILE__, __LINE__, "close failed %d", fd);
336 		}
337 		else {
338 			--(*ev->cur_fds);
339 		}
340 
341 		fdn_tmp = fdn;
342 		fdn = (fdnode *)fdn->ctx; /* next */
343 		/*(fdevent_unregister)*/
344 		fdnode_free(fdn_tmp);
345 		ev->fdarray[fd] = NULL;
346 	}
347 	ev->pendclose = NULL;
348 }
349 
350 __attribute_cold__
351 __attribute_noinline__
352 static int fdevent_fdnode_event_unsetter_retry(fdevents *ev, fdnode *fdn) {
353     do {
354         switch (errno) {
355          #ifdef EWOULDBLOCK
356          #if EAGAIN != EWOULDBLOCK
357           case EWOULDBLOCK:
358          #endif
359          #endif
360           case EAGAIN:
361           case EINTR:
362             /* temporary error; retry */
363             break;
364           /*case ENOMEM:*/
365           default:
366             /* unrecoverable error; might leak fd */
367             log_perror(ev->errh, __FILE__, __LINE__,
368               "fdevent event_del failed on fd %d", fdn->fd);
369             return 0;
370         }
371     } while (0 != ev->event_del(ev, fdn));
372     return 1;
373 }
374 
375 static void fdevent_fdnode_event_unsetter(fdevents *ev, fdnode *fdn) {
376     if (-1 == fdn->fde_ndx) return;
377     if (0 != ev->event_del(ev, fdn))
378         fdevent_fdnode_event_unsetter_retry(ev, fdn);
379     fdn->fde_ndx = -1;
380     fdn->events = 0;
381 }
382 
383 __attribute_cold__
384 __attribute_noinline__
385 static int fdevent_fdnode_event_setter_retry(fdevents *ev, fdnode *fdn, int events) {
386     do {
387         switch (errno) {
388          #ifdef EWOULDBLOCK
389          #if EAGAIN != EWOULDBLOCK
390           case EWOULDBLOCK:
391          #endif
392          #endif
393           case EAGAIN:
394           case EINTR:
395             /* temporary error; retry */
396             break;
397           /*case ENOMEM:*/
398           default:
399             /* unrecoverable error */
400             log_perror(ev->errh, __FILE__, __LINE__,
401               "fdevent event_set failed on fd %d", fdn->fd);
402             return 0;
403         }
404     } while (0 != ev->event_set(ev, fdn, events));
405     return 1;
406 }
407 
408 static void fdevent_fdnode_event_setter(fdevents *ev, fdnode *fdn, int events) {
409     /*(Note: skips registering with kernel if initial events is 0,
410      * so caller should pass non-zero events for initial registration.
411      * If never registered due to never being called with non-zero events,
412      * then FDEVENT_HUP or FDEVENT_ERR will never be returned.) */
413     if (fdn->events == events) return;/*(no change; nothing to do)*/
414 
415     if (0 == ev->event_set(ev, fdn, events)
416         || fdevent_fdnode_event_setter_retry(ev, fdn, events))
417         fdn->events = events;
418 }
419 
420 void fdevent_fdnode_event_del(fdevents *ev, fdnode *fdn) {
421     if (NULL != fdn) fdevent_fdnode_event_unsetter(ev, fdn);
422 }
423 
424 void fdevent_fdnode_event_set(fdevents *ev, fdnode *fdn, int events) {
425     if (NULL != fdn) fdevent_fdnode_event_setter(ev, fdn, events);
426 }
427 
428 void fdevent_fdnode_event_add(fdevents *ev, fdnode *fdn, int event) {
429     if (NULL != fdn) fdevent_fdnode_event_setter(ev, fdn, (fdn->events|event));
430 }
431 
432 void fdevent_fdnode_event_clr(fdevents *ev, fdnode *fdn, int event) {
433     if (NULL != fdn) fdevent_fdnode_event_setter(ev, fdn, (fdn->events&~event));
434 }
435 
436 int fdevent_poll(fdevents *ev, int timeout_ms) {
437     int n = ev->poll(ev, timeout_ms);
438     if (n >= 0)
439         fdevent_sched_run(ev);
440     else if (errno != EINTR)
441         log_perror(ev->errh, __FILE__, __LINE__, "fdevent_poll failed");
442     return n;
443 }
444 
445 void fdevent_setfd_cloexec(int fd) {
446 #ifdef FD_CLOEXEC
447 	if (fd < 0) return;
448 	force_assert(-1 != fcntl(fd, F_SETFD, FD_CLOEXEC));
449 #else
450 	UNUSED(fd);
451 #endif
452 }
453 
454 void fdevent_clrfd_cloexec(int fd) {
455 #ifdef FD_CLOEXEC
456 	if (fd >= 0) force_assert(-1 != fcntl(fd, F_SETFD, 0));
457 #else
458 	UNUSED(fd);
459 #endif
460 }
461 
462 int fdevent_fcntl_set_nb(int fd) {
463 #ifdef O_NONBLOCK
464 	return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
465 #else
466 	UNUSED(fd);
467 	return 0;
468 #endif
469 }
470 
471 int fdevent_fcntl_set_nb_cloexec(int fd) {
472 	fdevent_setfd_cloexec(fd);
473 	return fdevent_fcntl_set_nb(fd);
474 }
475 
476 int fdevent_fcntl_set_nb_cloexec_sock(int fd) {
477 #if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
478 	if (use_sock_cloexec && use_sock_nonblock)
479 		return 0;
480 #endif
481 	return fdevent_fcntl_set_nb_cloexec(fd);
482 }
483 
484 int fdevent_socket_cloexec(int domain, int type, int protocol) {
485 	int fd;
486 #ifdef SOCK_CLOEXEC
487 	if (use_sock_cloexec)
488 		return socket(domain, type | SOCK_CLOEXEC, protocol);
489 #endif
490 	if (-1 != (fd = socket(domain, type, protocol))) {
491 #ifdef FD_CLOEXEC
492 		force_assert(-1 != fcntl(fd, F_SETFD, FD_CLOEXEC));
493 #endif
494 	}
495 	return fd;
496 }
497 
498 int fdevent_socket_nb_cloexec(int domain, int type, int protocol) {
499 	int fd;
500 #ifdef SOCK_CLOEXEC
501        #ifdef SOCK_NONBLOCK
502 	if (use_sock_cloexec && use_sock_nonblock)
503 		return socket(domain, type | SOCK_CLOEXEC | SOCK_NONBLOCK, protocol);
504        #else
505 	if (use_sock_cloexec) {
506 		fd = socket(domain, type | SOCK_CLOEXEC, protocol);
507 	      #ifdef O_NONBLOCK
508 		if (-1 != fd) force_assert(-1 != fcntl(fd,F_SETFL,O_NONBLOCK|O_RDWR));
509 	      #endif
510 		return fd;
511 	}
512        #endif
513 #endif
514 	if (-1 != (fd = socket(domain, type, protocol))) {
515 #ifdef FD_CLOEXEC
516 		force_assert(-1 != fcntl(fd, F_SETFD, FD_CLOEXEC));
517 #endif
518 #ifdef O_NONBLOCK
519 		force_assert(-1 != fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR));
520 #endif
521 	}
522 	return fd;
523 }
524 
525 #ifndef O_BINARY
526 #define O_BINARY 0
527 #endif
528 #ifndef O_LARGEFILE
529 #define O_LARGEFILE 0
530 #endif
531 #ifndef O_NOCTTY
532 #define O_NOCTTY 0
533 #endif
534 #ifndef O_NOFOLLOW
535 #define O_NOFOLLOW 0
536 #endif
537 
538 /*(O_NOFOLLOW is not handled here)*/
539 /*(Note: O_NOFOLLOW affects only the final path segment, the target file,
540  * not any intermediate symlinks along the path)*/
541 
542 /* O_CLOEXEC handled further below, if defined) */
543 #ifdef O_NONBLOCK
544 #define FDEVENT_O_FLAGS \
545         (O_BINARY | O_LARGEFILE | O_NOCTTY | O_NONBLOCK)
546 #else
547 #define FDEVENT_O_FLAGS \
548         (O_BINARY | O_LARGEFILE | O_NOCTTY )
549 #endif
550 
551 int fdevent_open_cloexec(const char *pathname, int symlinks, int flags, mode_t mode) {
552 	if (!symlinks) flags |= O_NOFOLLOW;
553 #ifdef O_CLOEXEC
554 	return open(pathname, flags | O_CLOEXEC | FDEVENT_O_FLAGS, mode);
555 #else
556 	int fd = open(pathname, flags | FDEVENT_O_FLAGS, mode);
557 #ifdef FD_CLOEXEC
558 	if (fd != -1)
559 		force_assert(-1 != fcntl(fd, F_SETFD, FD_CLOEXEC));
560 #endif
561 	return fd;
562 #endif
563 }
564 
565 
566 int fdevent_open_devnull(void) {
567   #if defined(_WIN32)
568     return fdevent_open_cloexec("nul", 0, O_RDWR, 0);
569   #else
570     return fdevent_open_cloexec("/dev/null", 0, O_RDWR, 0);
571   #endif
572 }
573 
574 
575 int fdevent_open_dirname(char *path, int symlinks) {
576     /*(handle special cases of no dirname or dirname is root directory)*/
577     char * const c = strrchr(path, '/');
578     const char * const dname = (NULL != c ? c == path ? "/" : path : ".");
579     int dfd;
580     int flags = O_RDONLY;
581   #ifdef O_DIRECTORY
582     flags |= O_DIRECTORY;
583   #endif
584     if (NULL != c) *c = '\0';
585     dfd = fdevent_open_cloexec(dname, symlinks, flags, 0);
586     if (NULL != c) *c = '/';
587     return dfd;
588 }
589 
590 
591 int fdevent_mkstemp_append(char *path) {
592   #ifdef __COVERITY__
593     /* POSIX-2008 requires mkstemp create file with 0600 perms */
594     umask(0600);
595   #endif
596     /* coverity[secure_temp : FALSE] */
597     const int fd = mkstemp(path);
598     if (fd < 0) return fd;
599 
600     if (0 != fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_APPEND)) {
601         /* (should not happen; fd is regular file) */
602         int errnum = errno;
603         close(fd);
604         errno = errnum;
605         return -1;
606     }
607 
608     fdevent_setfd_cloexec(fd);
609     return fd;
610 }
611 
612 
613 int fdevent_accept_listenfd(int listenfd, struct sockaddr *addr, size_t *addrlen) {
614 	int fd;
615 	socklen_t len = (socklen_t) *addrlen;
616 
617       #if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
618        #if defined(__NetBSD__)
619 	const int sock_cloexec = 1;
620 	fd = paccept(listenfd, addr, &len, NULL, SOCK_CLOEXEC | SOCK_NONBLOCK);
621        #else
622 	int sock_cloexec = use_sock_cloexec;
623 	if (sock_cloexec) {
624 		fd = accept4(listenfd, addr, &len, SOCK_CLOEXEC | SOCK_NONBLOCK);
625 		if (fd >= 0) {
626 			if (!use_sock_nonblock) {
627 				if (0 != fdevent_fcntl_set_nb(fd)) {
628 					close(fd);
629 					fd = -1;
630 				}
631 			}
632 		}
633 		else {
634 			switch (errno) {
635 			case ENOSYS:
636 			case ENOTSUP:
637 			case EPERM:
638 				fd = accept(listenfd, addr, &len);
639 				sock_cloexec = 0;
640 				break;
641 			default:
642 				break;
643 			}
644 		}
645 	}
646 	else {
647 		fd = accept(listenfd, addr, &len);
648 	}
649        #endif
650       #else
651 	const int sock_cloexec = 0;
652 	fd = accept(listenfd, addr, &len);
653       #endif
654 
655 	if (fd >= 0) {
656 		*addrlen = (size_t)len;
657 		if (!sock_cloexec && 0 != fdevent_fcntl_set_nb_cloexec(fd)) {
658 			close(fd);
659 			fd = -1;
660 		}
661 	}
662 	return fd;
663 }
664 
665 
666 #ifdef __APPLE__
667 #include <crt_externs.h>
668 #define environ (* _NSGetEnviron())
669 #else
670 extern char **environ;
671 #endif
672 char ** fdevent_environ (void) { return environ; }
673 
674 
675 #ifdef FD_CLOEXEC
676 static int fdevent_dup2_close_clrfd_cloexec(int oldfd, int newfd) {
677     if (oldfd >= 0) {
678         if (oldfd != newfd) {
679             force_assert(oldfd > STDERR_FILENO);
680             if (newfd != dup2(oldfd, newfd)) return -1;
681         }
682         else {
683             fdevent_clrfd_cloexec(newfd);
684         }
685     }
686     return newfd;
687 }
688 #else
689 static int fdevent_dup2_close_clrfd_cloexec(int oldfd, int newfd, int reuse) {
690     if (oldfd >= 0) {
691         if (oldfd != newfd) {
692             force_assert(oldfd > STDERR_FILENO);
693             if (newfd != dup2(oldfd, newfd)) return -1;
694             if (!reuse) close(oldfd);
695         }
696     }
697     return newfd;
698 }
699 #endif
700 
701 
702 int fdevent_set_stdin_stdout_stderr(int fdin, int fdout, int fderr) {
703   #ifdef FD_CLOEXEC
704     if (STDIN_FILENO != fdevent_dup2_close_clrfd_cloexec(fdin, STDIN_FILENO))
705         return -1;
706     if (STDOUT_FILENO != fdevent_dup2_close_clrfd_cloexec(fdout, STDOUT_FILENO))
707         return -1;
708     if (STDERR_FILENO != fdevent_dup2_close_clrfd_cloexec(fderr, STDERR_FILENO))
709         return -1;
710   #else
711     if (STDIN_FILENO != fdevent_dup2_close_clrfd_cloexec(fdin, STDIN_FILENO,
712                                                          fdin == fdout
713                                                          || fdin == fderr))
714         return -1;
715     if (STDOUT_FILENO != fdevent_dup2_close_clrfd_cloexec(fdout, STDOUT_FILENO,
716                                                           fdout == fderr))
717         return -1;
718     if (STDERR_FILENO != fdevent_dup2_close_clrfd_cloexec(fderr, STDERR_FILENO,
719                                                           0))
720         return -1;
721   #endif
722 
723     return 0;
724 }
725 
726 
727 #include <stdio.h>      /* perror() */
728 #include <signal.h>     /* signal() */
729 
730 pid_t fdevent_fork_execve(const char *name, char *argv[], char *envp[], int fdin, int fdout, int fderr, int dfd) {
731  #ifdef HAVE_FORK
732 
733     pid_t pid = fork();
734     if (0 != pid) return pid; /* parent (pid > 0) or fork() error (-1 == pid) */
735 
736     /* child (0 == pid) */
737 
738     if (-1 != dfd) {
739         if (0 != fchdir(dfd))
740             _exit(errno);
741         close(dfd);
742     }
743 
744     if (0 != fdevent_set_stdin_stdout_stderr(fdin, fdout, fderr)) _exit(errno);
745   #ifdef FD_CLOEXEC
746     /*(might not be sufficient for open fds, but modern OS have FD_CLOEXEC)*/
747     for (int i = 3; i < 256; ++i) close(i);
748   #endif
749 
750     /* reset_signals which may have been ignored (SIG_IGN) */
751   #ifdef SIGTTOU
752     signal(SIGTTOU, SIG_DFL);
753   #endif
754   #ifdef SIGTTIN
755     signal(SIGTTIN, SIG_DFL);
756   #endif
757   #ifdef SIGTSTP
758     signal(SIGTSTP, SIG_DFL);
759   #endif
760     signal(SIGPIPE, SIG_DFL);
761 
762     execve(name, argv, envp ? envp : environ);
763 
764     int errnum = errno;
765     if (0 == memcmp(argv[0], "/bin/sh", sizeof("/bin/sh")-1)
766         && argv[1] && 0 == memcmp(argv[1], "-c", sizeof("-c")-1))
767         perror(argv[2]);
768     else
769         perror(argv[0]);
770     _exit(errnum);
771 
772  #else
773 
774     UNUSED(name);
775     UNUSED(argv);
776     UNUSED(envp);
777     UNUSED(fdin);
778     UNUSED(fdout);
779     UNUSED(fderr);
780     UNUSED(dfd);
781     return (pid_t)-1;
782 
783  #endif
784 }
785 
786 
787 typedef struct fdevent_cmd_pipe {
788     pid_t pid;
789     int fds[2];
790     const char *cmd;
791     time_t start;
792 } fdevent_cmd_pipe;
793 
794 typedef struct fdevent_cmd_pipes {
795     fdevent_cmd_pipe *ptr;
796     uint32_t used;
797     uint32_t size;
798 } fdevent_cmd_pipes;
799 
800 static fdevent_cmd_pipes cmd_pipes;
801 
802 
803 static pid_t fdevent_open_logger_pipe_spawn(const char *logger, int rfd) {
804     char *args[4];
805     int devnull = fdevent_open_devnull();
806     pid_t pid;
807 
808     if (-1 == devnull) {
809         return -1;
810     }
811 
812     *(const char **)&args[0] = "/bin/sh";
813     *(const char **)&args[1] = "-c";
814     *(const char **)&args[2] = logger;
815     args[3] = NULL;
816 
817     pid = fdevent_fork_execve(args[0], args, NULL, rfd, devnull, devnull, -1);
818 
819     if (pid > 0) {
820         close(devnull);
821     }
822     else {
823         int errnum = errno;
824         close(devnull);
825         errno = errnum;
826     }
827     return pid;
828 }
829 
830 
831 static void fdevent_restart_logger_pipe(fdevent_cmd_pipe *fcp, time_t ts) {
832     if (fcp->pid > 0) return;  /* assert */
833     if (fcp->start + 5 < ts) { /* limit restart to once every 5 sec */
834         /* restart child process using existing pipe fds */
835         fcp->start = ts;
836         fcp->pid = fdevent_open_logger_pipe_spawn(fcp->cmd, fcp->fds[0]);
837     }
838 }
839 
840 
841 void fdevent_restart_logger_pipes(time_t ts) {
842     for (uint32_t i = 0; i < cmd_pipes.used; ++i) {
843         fdevent_cmd_pipe * const fcp = cmd_pipes.ptr+i;
844         if (fcp->pid > 0) continue;
845         fdevent_restart_logger_pipe(fcp, ts);
846     }
847 }
848 
849 
850 int fdevent_waitpid_logger_pipe_pid(pid_t pid, time_t ts) {
851     for (uint32_t i = 0; i < cmd_pipes.used; ++i) {
852         fdevent_cmd_pipe * const fcp = cmd_pipes.ptr+i;
853         if (pid != fcp->pid) continue;
854         fcp->pid = -1;
855         fdevent_restart_logger_pipe(fcp, ts);
856         return 1;
857     }
858     return 0;
859 }
860 
861 
862 void fdevent_clr_logger_pipe_pids(void) {
863     for (uint32_t i = 0; i < cmd_pipes.used; ++i) {
864         fdevent_cmd_pipe *fcp = cmd_pipes.ptr+i;
865         fcp->pid = -1;
866     }
867 }
868 
869 
870 int fdevent_reaped_logger_pipe(pid_t pid) {
871     for (uint32_t i = 0; i < cmd_pipes.used; ++i) {
872         fdevent_cmd_pipe *fcp = cmd_pipes.ptr+i;
873         if (fcp->pid == pid) {
874             time_t ts = time(NULL);
875             if (fcp->start + 5 < ts) { /* limit restart to once every 5 sec */
876                 fcp->start = ts;
877                 fcp->pid = fdevent_open_logger_pipe_spawn(fcp->cmd,fcp->fds[0]);
878                 return (fcp->pid > 0) ? 1 : -1;
879             }
880             else {
881                 fcp->pid = -1;
882                 return -1;
883             }
884         }
885     }
886     return 0;
887 }
888 
889 
890 void fdevent_close_logger_pipes(void) {
891     for (uint32_t i = 0; i < cmd_pipes.used; ++i) {
892         fdevent_cmd_pipe *fcp = cmd_pipes.ptr+i;
893         close(fcp->fds[0]);
894         if (fcp->fds[1] != STDERR_FILENO) close(fcp->fds[1]);
895     }
896     free(cmd_pipes.ptr);
897     cmd_pipes.ptr = NULL;
898     cmd_pipes.used = 0;
899     cmd_pipes.size = 0;
900 }
901 
902 
903 void fdevent_breakagelog_logger_pipe(int fd) {
904     for (uint32_t i = 0; i < cmd_pipes.used; ++i) {
905         fdevent_cmd_pipe *fcp = cmd_pipes.ptr+i;
906         if (fcp->fds[1] != fd) continue;
907         fcp->fds[1] = STDERR_FILENO;
908         break;
909     }
910 }
911 
912 
913 static void fdevent_init_logger_pipe(const char *cmd, int fds[2], pid_t pid) {
914     fdevent_cmd_pipe *fcp;
915     if (cmd_pipes.used == cmd_pipes.size) {
916         cmd_pipes.size += 4;
917         cmd_pipes.ptr =
918           realloc(cmd_pipes.ptr, cmd_pipes.size * sizeof(fdevent_cmd_pipe));
919         force_assert(cmd_pipes.ptr);
920     }
921     fcp = cmd_pipes.ptr + cmd_pipes.used++;
922     fcp->cmd = cmd; /* note: cmd must persist in memory (or else copy here) */
923     fcp->fds[0] = fds[0];
924     fcp->fds[1] = fds[1];
925     fcp->pid = pid;
926     fcp->start = time(NULL);
927 }
928 
929 
930 static int fdevent_open_logger_pipe(const char *logger) {
931     int fds[2];
932     pid_t pid;
933     if (pipe(fds)) {
934         return -1;
935     }
936     fdevent_setfd_cloexec(fds[0]);
937     fdevent_setfd_cloexec(fds[1]);
938     /*(nonblocking write() from lighttpd)*/
939     if (0 != fdevent_fcntl_set_nb(fds[1])) { /*(ignore)*/ }
940 
941     pid = fdevent_open_logger_pipe_spawn(logger, fds[0]);
942 
943     if (pid > 0) {
944         fdevent_init_logger_pipe(logger, fds, pid);
945         return fds[1];
946     }
947     else {
948         int errnum = errno;
949         close(fds[0]);
950         close(fds[1]);
951         errno = errnum;
952         return -1;
953     }
954 }
955 
956 
957 int fdevent_open_logger(const char *logger) {
958     if (logger[0] != '|') { /*(permit symlinks)*/
959         int flags = O_APPEND | O_WRONLY | O_CREAT;
960         return fdevent_open_cloexec(logger, 1, flags, 0644);
961     }
962     else {
963         return fdevent_open_logger_pipe(logger+1); /*(skip the '|')*/
964     }
965 }
966 
967 int fdevent_cycle_logger(const char *logger, int *curfd) {
968     if (logger[0] != '|') {
969         int fd = fdevent_open_logger(logger);
970         if (-1 == fd) return -1; /*(error; leave *curfd as-is)*/
971         if (-1 != *curfd) close(*curfd);
972         *curfd = fd;
973     }
974     return *curfd;
975 }
976 
977 
978 #ifndef MSG_DONTWAIT
979 #define MSG_DONTWAIT 0
980 #endif
981 #ifndef MSG_NOSIGNAL
982 #define MSG_NOSIGNAL 0
983 #endif
984 
985 
986 ssize_t fdevent_socket_read_discard (int fd, char *buf, size_t sz, int family, int so_type) {
987   #if defined(MSG_TRUNC) && defined(__linux__)
988     if ((family == AF_INET || family == AF_INET6) && so_type == SOCK_STREAM) {
989         ssize_t len = recv(fd, buf, sz, MSG_TRUNC|MSG_DONTWAIT|MSG_NOSIGNAL);
990         if (len >= 0 || errno != EINVAL) return len;
991     }
992   #else
993     UNUSED(family);
994     UNUSED(so_type);
995   #endif
996     return read(fd, buf, sz);
997 }
998 
999 
1000 #include <sys/ioctl.h>
1001 #ifdef HAVE_SYS_FILIO_H
1002 #include <sys/filio.h>  /* FIONREAD (for illumos (OpenIndiana)) */
1003 #endif
1004 #ifdef _WIN32
1005 #include <winsock2.h>
1006 #endif
1007 int fdevent_ioctl_fionread (int fd, int fdfmt, int *toread) {
1008   #ifdef _WIN32
1009     if (fdfmt != S_IFSOCK) { errno = ENOTSOCK; return -1; }
1010     return ioctlsocket(fd, FIONREAD, toread);
1011   #else
1012    #ifdef __CYGWIN__
1013     /*(cygwin supports FIONREAD on pipes, not sockets)*/
1014     if (fdfmt != S_IFIFO) { errno = EOPNOTSUPP; return -1; }
1015    #else
1016     UNUSED(fdfmt);
1017    #endif
1018     return ioctl(fd, FIONREAD, toread);
1019   #endif
1020 }
1021 
1022 
1023 int fdevent_connect_status(int fd) {
1024     /* try to finish the connect() */
1025     /*(should be called after connect() only when fd is writable (POLLOUT))*/
1026     int opt;
1027     socklen_t len = sizeof(opt);
1028     return (0 == getsockopt(fd,SOL_SOCKET,SO_ERROR,&opt,&len)) ? opt : errno;
1029 }
1030 
1031 
1032 #include <netinet/tcp.h>
1033 #if (defined(__APPLE__) && defined(__MACH__)) \
1034   || defined(__FreeBSD__) || defined(__NetBSD__) \
1035   || defined(__OpenBSD__) || defined(__DragonFly__)
1036 #include <netinet/tcp_fsm.h>
1037 #endif
1038 
1039 /* fd must be TCP socket (AF_INET, AF_INET6), end-of-stream recv() 0 bytes */
1040 int fdevent_is_tcp_half_closed(int fd) {
1041   #ifdef TCP_CONNECTION_INFO     /* Darwin */
1042     struct tcp_connection_info tcpi;
1043     socklen_t tlen = sizeof(tcpi);
1044     return (0 == getsockopt(fd, IPPROTO_TCP, TCP_CONNECTION_INFO, &tcpi, &tlen)
1045             && tcpi.tcpi_state == TCPS_CLOSE_WAIT);
1046   #elif defined(TCP_INFO) && defined(TCPS_CLOSE_WAIT)
1047     /* FreeBSD, NetBSD (not present in OpenBSD or DragonFlyBSD) */
1048     struct tcp_info tcpi;
1049     socklen_t tlen = sizeof(tcpi);
1050     return (0 == getsockopt(fd, IPPROTO_TCP, TCP_INFO, &tcpi, &tlen)
1051             && tcpi.tcpi_state == TCPS_CLOSE_WAIT);
1052   #elif defined(TCP_INFO) && defined(__linux__)
1053     /* Linux (TCP_CLOSE_WAIT is enum, so can not #ifdef TCP_CLOSE_WAIT) */
1054     struct tcp_info tcpi;
1055     socklen_t tlen = sizeof(tcpi);/*SOL_TCP == IPPROTO_TCP*/
1056     return (0 == getsockopt(fd,     SOL_TCP, TCP_INFO, &tcpi, &tlen)
1057             && tcpi.tcpi_state == TCP_CLOSE_WAIT);
1058   #else
1059     UNUSED(fd);
1060     /*(0 != getpeername() error might indicate TCP RST, but success
1061      * would not differentiate between half-close and full-close)*/
1062     return 0; /* false (not half-closed) or TCP state unknown */
1063   #endif
1064 }
1065 
1066 
1067 int fdevent_set_tcp_nodelay (const int fd, const int opt)
1068 {
1069     return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
1070 }
1071 
1072 
1073 int fdevent_set_so_reuseaddr (const int fd, const int opt)
1074 {
1075     return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
1076 }
1077