xref: /lighttpd1.4/src/fdevent.c (revision 2f7839e8)
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 int fdevent_dup_cloexec (int fd) {
526   #ifdef F_DUPFD_CLOEXEC
527     return fcntl(fd, F_DUPFD_CLOEXEC, 3);
528   #else
529     const int newfd = fcntl(fd, F_DUPFD, 3);
530     if (newfd >= 0) fdevent_setfd_cloexec(newfd);
531     return newfd;
532   #endif
533 }
534 
535 #ifndef O_BINARY
536 #define O_BINARY 0
537 #endif
538 #ifndef O_LARGEFILE
539 #define O_LARGEFILE 0
540 #endif
541 #ifndef O_NOCTTY
542 #define O_NOCTTY 0
543 #endif
544 #ifndef O_NOFOLLOW
545 #define O_NOFOLLOW 0
546 #endif
547 
548 /*(O_NOFOLLOW is not handled here)*/
549 /*(Note: O_NOFOLLOW affects only the final path segment, the target file,
550  * not any intermediate symlinks along the path)*/
551 
552 /* O_CLOEXEC handled further below, if defined) */
553 #ifdef O_NONBLOCK
554 #define FDEVENT_O_FLAGS \
555         (O_BINARY | O_LARGEFILE | O_NOCTTY | O_NONBLOCK)
556 #else
557 #define FDEVENT_O_FLAGS \
558         (O_BINARY | O_LARGEFILE | O_NOCTTY )
559 #endif
560 
561 int fdevent_open_cloexec(const char *pathname, int symlinks, int flags, mode_t mode) {
562 	if (!symlinks) flags |= O_NOFOLLOW;
563 #ifdef O_CLOEXEC
564 	return open(pathname, flags | O_CLOEXEC | FDEVENT_O_FLAGS, mode);
565 #else
566 	int fd = open(pathname, flags | FDEVENT_O_FLAGS, mode);
567 #ifdef FD_CLOEXEC
568 	if (fd != -1)
569 		force_assert(-1 != fcntl(fd, F_SETFD, FD_CLOEXEC));
570 #endif
571 	return fd;
572 #endif
573 }
574 
575 
576 int fdevent_open_devnull(void) {
577   #if defined(_WIN32)
578     return fdevent_open_cloexec("nul", 0, O_RDWR, 0);
579   #else
580     return fdevent_open_cloexec("/dev/null", 0, O_RDWR, 0);
581   #endif
582 }
583 
584 
585 int fdevent_open_dirname(char *path, int symlinks) {
586     /*(handle special cases of no dirname or dirname is root directory)*/
587     char * const c = strrchr(path, '/');
588     const char * const dname = (NULL != c ? c == path ? "/" : path : ".");
589     int dfd;
590     int flags = O_RDONLY;
591   #ifdef O_DIRECTORY
592     flags |= O_DIRECTORY;
593   #endif
594     if (NULL != c) *c = '\0';
595     dfd = fdevent_open_cloexec(dname, symlinks, flags, 0);
596     if (NULL != c) *c = '/';
597     return dfd;
598 }
599 
600 
601 int fdevent_mkstemp_append(char *path) {
602   #ifdef __COVERITY__
603     /* POSIX-2008 requires mkstemp create file with 0600 perms */
604     umask(0600);
605   #endif
606     /* coverity[secure_temp : FALSE] */
607     const int fd = mkstemp(path);
608     if (fd < 0) return fd;
609 
610     if (0 != fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_APPEND)) {
611         /* (should not happen; fd is regular file) */
612         int errnum = errno;
613         close(fd);
614         errno = errnum;
615         return -1;
616     }
617 
618     fdevent_setfd_cloexec(fd);
619     return fd;
620 }
621 
622 
623 int fdevent_accept_listenfd(int listenfd, struct sockaddr *addr, size_t *addrlen) {
624 	int fd;
625 	socklen_t len = (socklen_t) *addrlen;
626 
627       #if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
628        #if defined(__NetBSD__)
629 	const int sock_cloexec = 1;
630 	fd = paccept(listenfd, addr, &len, NULL, SOCK_CLOEXEC | SOCK_NONBLOCK);
631        #else
632 	int sock_cloexec = use_sock_cloexec;
633 	if (sock_cloexec) {
634 		fd = accept4(listenfd, addr, &len, SOCK_CLOEXEC | SOCK_NONBLOCK);
635 		if (fd >= 0) {
636 			if (!use_sock_nonblock) {
637 				if (0 != fdevent_fcntl_set_nb(fd)) {
638 					close(fd);
639 					fd = -1;
640 				}
641 			}
642 		}
643 		else {
644 			switch (errno) {
645 			case ENOSYS:
646 			case ENOTSUP:
647 			case EPERM:
648 				fd = accept(listenfd, addr, &len);
649 				sock_cloexec = 0;
650 				break;
651 			default:
652 				break;
653 			}
654 		}
655 	}
656 	else {
657 		fd = accept(listenfd, addr, &len);
658 	}
659        #endif
660       #else
661 	const int sock_cloexec = 0;
662 	fd = accept(listenfd, addr, &len);
663       #endif
664 
665 	if (fd >= 0) {
666 		*addrlen = (size_t)len;
667 		if (!sock_cloexec && 0 != fdevent_fcntl_set_nb_cloexec(fd)) {
668 			close(fd);
669 			fd = -1;
670 		}
671 	}
672 	return fd;
673 }
674 
675 
676 #ifdef __APPLE__
677 #include <crt_externs.h>
678 #define environ (* _NSGetEnviron())
679 #else
680 extern char **environ;
681 #endif
682 char ** fdevent_environ (void) { return environ; }
683 
684 
685 #ifdef FD_CLOEXEC
686 static int fdevent_dup2_close_clrfd_cloexec(int oldfd, int newfd) {
687     if (oldfd >= 0) {
688         if (oldfd != newfd) {
689             force_assert(oldfd > STDERR_FILENO);
690             if (newfd != dup2(oldfd, newfd)) return -1;
691         }
692         else {
693             fdevent_clrfd_cloexec(newfd);
694         }
695     }
696     return newfd;
697 }
698 #else
699 static int fdevent_dup2_close_clrfd_cloexec(int oldfd, int newfd, int reuse) {
700     if (oldfd >= 0) {
701         if (oldfd != newfd) {
702             force_assert(oldfd > STDERR_FILENO);
703             if (newfd != dup2(oldfd, newfd)) return -1;
704             if (!reuse) close(oldfd);
705         }
706     }
707     return newfd;
708 }
709 #endif
710 
711 
712 int fdevent_set_stdin_stdout_stderr(int fdin, int fdout, int fderr) {
713   #ifdef FD_CLOEXEC
714     if (STDIN_FILENO != fdevent_dup2_close_clrfd_cloexec(fdin, STDIN_FILENO))
715         return -1;
716     if (STDOUT_FILENO != fdevent_dup2_close_clrfd_cloexec(fdout, STDOUT_FILENO))
717         return -1;
718     if (STDERR_FILENO != fdevent_dup2_close_clrfd_cloexec(fderr, STDERR_FILENO))
719         return -1;
720   #else
721     if (STDIN_FILENO != fdevent_dup2_close_clrfd_cloexec(fdin, STDIN_FILENO,
722                                                          fdin == fdout
723                                                          || fdin == fderr))
724         return -1;
725     if (STDOUT_FILENO != fdevent_dup2_close_clrfd_cloexec(fdout, STDOUT_FILENO,
726                                                           fdout == fderr))
727         return -1;
728     if (STDERR_FILENO != fdevent_dup2_close_clrfd_cloexec(fderr, STDERR_FILENO,
729                                                           0))
730         return -1;
731   #endif
732 
733     return 0;
734 }
735 
736 
737 #include <stdio.h>      /* perror() rename() */
738 #include <signal.h>     /* signal() */
739 
740 
741 int fdevent_rename(const char *oldpath, const char *newpath) {
742     return rename(oldpath, newpath);
743 }
744 
745 
746 pid_t fdevent_fork_execve(const char *name, char *argv[], char *envp[], int fdin, int fdout, int fderr, int dfd) {
747  #ifdef HAVE_FORK
748 
749     pid_t pid = fork();
750     if (0 != pid) return pid; /* parent (pid > 0) or fork() error (-1 == pid) */
751 
752     /* child (0 == pid) */
753 
754     if (-1 != dfd) {
755         if (0 != fchdir(dfd))
756             _exit(errno);
757         close(dfd);
758     }
759 
760     if (0 != fdevent_set_stdin_stdout_stderr(fdin, fdout, fderr)) _exit(errno);
761   #ifndef FD_CLOEXEC
762     /*(might not be sufficient for open fds, but modern OS have FD_CLOEXEC)*/
763     for (int i = 3; i < 256; ++i) close(i);
764   #endif
765 
766     /* reset_signals which may have been ignored (SIG_IGN) */
767   #ifdef SIGTTOU
768     signal(SIGTTOU, SIG_DFL);
769   #endif
770   #ifdef SIGTTIN
771     signal(SIGTTIN, SIG_DFL);
772   #endif
773   #ifdef SIGTSTP
774     signal(SIGTSTP, SIG_DFL);
775   #endif
776     signal(SIGPIPE, SIG_DFL);
777 
778     execve(name, argv, envp ? envp : environ);
779 
780     int errnum = errno;
781     if (0 == memcmp(argv[0], "/bin/sh", sizeof("/bin/sh")-1)
782         && argv[1] && 0 == memcmp(argv[1], "-c", sizeof("-c")-1))
783         perror(argv[2]);
784     else
785         perror(argv[0]);
786     _exit(errnum);
787 
788  #else
789 
790     UNUSED(name);
791     UNUSED(argv);
792     UNUSED(envp);
793     UNUSED(fdin);
794     UNUSED(fdout);
795     UNUSED(fderr);
796     UNUSED(dfd);
797     return (pid_t)-1;
798 
799  #endif
800 }
801 
802 
803 typedef struct fdevent_cmd_pipe {
804     pid_t pid;
805     int fds[2];
806     const char *cmd;
807     time_t start;
808 } fdevent_cmd_pipe;
809 
810 typedef struct fdevent_cmd_pipes {
811     fdevent_cmd_pipe *ptr;
812     uint32_t used;
813     uint32_t size;
814 } fdevent_cmd_pipes;
815 
816 static fdevent_cmd_pipes cmd_pipes;
817 
818 
819 static pid_t fdevent_open_logger_pipe_spawn(const char *logger, int rfd) {
820     char *args[4];
821     int devnull = fdevent_open_devnull();
822     pid_t pid;
823 
824     if (-1 == devnull) {
825         return -1;
826     }
827 
828     *(const char **)&args[0] = "/bin/sh";
829     *(const char **)&args[1] = "-c";
830     *(const char **)&args[2] = logger;
831     args[3] = NULL;
832 
833     pid = fdevent_fork_execve(args[0], args, NULL, rfd, devnull, devnull, -1);
834 
835     if (pid > 0) {
836         close(devnull);
837     }
838     else {
839         int errnum = errno;
840         close(devnull);
841         errno = errnum;
842     }
843     return pid;
844 }
845 
846 
847 static void fdevent_restart_logger_pipe(fdevent_cmd_pipe *fcp, time_t ts) {
848     if (fcp->pid > 0) return;  /* assert */
849     if (fcp->start + 5 < ts) { /* limit restart to once every 5 sec */
850         /* restart child process using existing pipe fds */
851         fcp->start = ts;
852         fcp->pid = fdevent_open_logger_pipe_spawn(fcp->cmd, fcp->fds[0]);
853     }
854 }
855 
856 
857 void fdevent_restart_logger_pipes(time_t ts) {
858     for (uint32_t i = 0; i < cmd_pipes.used; ++i) {
859         fdevent_cmd_pipe * const fcp = cmd_pipes.ptr+i;
860         if (fcp->pid > 0) continue;
861         fdevent_restart_logger_pipe(fcp, ts);
862     }
863 }
864 
865 
866 int fdevent_waitpid_logger_pipe_pid(pid_t pid, time_t ts) {
867     for (uint32_t i = 0; i < cmd_pipes.used; ++i) {
868         fdevent_cmd_pipe * const fcp = cmd_pipes.ptr+i;
869         if (pid != fcp->pid) continue;
870         fcp->pid = -1;
871         fdevent_restart_logger_pipe(fcp, ts);
872         return 1;
873     }
874     return 0;
875 }
876 
877 
878 void fdevent_clr_logger_pipe_pids(void) {
879     for (uint32_t i = 0; i < cmd_pipes.used; ++i) {
880         fdevent_cmd_pipe *fcp = cmd_pipes.ptr+i;
881         fcp->pid = -1;
882     }
883 }
884 
885 
886 int fdevent_reaped_logger_pipe(pid_t pid) {
887     for (uint32_t i = 0; i < cmd_pipes.used; ++i) {
888         fdevent_cmd_pipe *fcp = cmd_pipes.ptr+i;
889         if (fcp->pid == pid) {
890             time_t ts = time(NULL);
891             if (fcp->start + 5 < ts) { /* limit restart to once every 5 sec */
892                 fcp->start = ts;
893                 fcp->pid = fdevent_open_logger_pipe_spawn(fcp->cmd,fcp->fds[0]);
894                 return (fcp->pid > 0) ? 1 : -1;
895             }
896             else {
897                 fcp->pid = -1;
898                 return -1;
899             }
900         }
901     }
902     return 0;
903 }
904 
905 
906 void fdevent_close_logger_pipes(void) {
907     for (uint32_t i = 0; i < cmd_pipes.used; ++i) {
908         fdevent_cmd_pipe *fcp = cmd_pipes.ptr+i;
909         close(fcp->fds[0]);
910         if (fcp->fds[1] != STDERR_FILENO) close(fcp->fds[1]);
911     }
912     free(cmd_pipes.ptr);
913     cmd_pipes.ptr = NULL;
914     cmd_pipes.used = 0;
915     cmd_pipes.size = 0;
916 }
917 
918 
919 void fdevent_breakagelog_logger_pipe(int fd) {
920     for (uint32_t i = 0; i < cmd_pipes.used; ++i) {
921         fdevent_cmd_pipe *fcp = cmd_pipes.ptr+i;
922         if (fcp->fds[1] != fd) continue;
923         fcp->fds[1] = STDERR_FILENO;
924         break;
925     }
926 }
927 
928 
929 static void fdevent_init_logger_pipe(const char *cmd, int fds[2], pid_t pid) {
930     fdevent_cmd_pipe *fcp;
931     if (cmd_pipes.used == cmd_pipes.size) {
932         cmd_pipes.size += 4;
933         cmd_pipes.ptr =
934           realloc(cmd_pipes.ptr, cmd_pipes.size * sizeof(fdevent_cmd_pipe));
935         force_assert(cmd_pipes.ptr);
936     }
937     fcp = cmd_pipes.ptr + cmd_pipes.used++;
938     fcp->cmd = cmd; /* note: cmd must persist in memory (or else copy here) */
939     fcp->fds[0] = fds[0];
940     fcp->fds[1] = fds[1];
941     fcp->pid = pid;
942     fcp->start = time(NULL);
943 }
944 
945 
946 static int fdevent_open_logger_pipe(const char *logger) {
947     int fds[2];
948     pid_t pid;
949     if (pipe(fds)) {
950         return -1;
951     }
952     fdevent_setfd_cloexec(fds[0]);
953     fdevent_setfd_cloexec(fds[1]);
954     /*(nonblocking write() from lighttpd)*/
955     if (0 != fdevent_fcntl_set_nb(fds[1])) { /*(ignore)*/ }
956 
957     pid = fdevent_open_logger_pipe_spawn(logger, fds[0]);
958 
959     if (pid > 0) {
960         fdevent_init_logger_pipe(logger, fds, pid);
961         return fds[1];
962     }
963     else {
964         int errnum = errno;
965         close(fds[0]);
966         close(fds[1]);
967         errno = errnum;
968         return -1;
969     }
970 }
971 
972 
973 int fdevent_open_logger(const char *logger) {
974     if (logger[0] != '|') { /*(permit symlinks)*/
975         int flags = O_APPEND | O_WRONLY | O_CREAT;
976         return fdevent_open_cloexec(logger, 1, flags, 0644);
977     }
978     else {
979         return fdevent_open_logger_pipe(logger+1); /*(skip the '|')*/
980     }
981 }
982 
983 int fdevent_cycle_logger(const char *logger, int *curfd) {
984     if (logger[0] != '|') {
985         int fd = fdevent_open_logger(logger);
986         if (-1 == fd) return -1; /*(error; leave *curfd as-is)*/
987         if (-1 != *curfd) close(*curfd);
988         *curfd = fd;
989     }
990     return *curfd;
991 }
992 
993 
994 #ifndef MSG_DONTWAIT
995 #define MSG_DONTWAIT 0
996 #endif
997 #ifndef MSG_NOSIGNAL
998 #define MSG_NOSIGNAL 0
999 #endif
1000 
1001 
1002 ssize_t fdevent_socket_read_discard (int fd, char *buf, size_t sz, int family, int so_type) {
1003   #if defined(MSG_TRUNC) && defined(__linux__)
1004     if ((family == AF_INET || family == AF_INET6) && so_type == SOCK_STREAM) {
1005         ssize_t len = recv(fd, buf, sz, MSG_TRUNC|MSG_DONTWAIT|MSG_NOSIGNAL);
1006         if (len >= 0 || errno != EINVAL) return len;
1007     }
1008   #else
1009     UNUSED(family);
1010     UNUSED(so_type);
1011   #endif
1012     return read(fd, buf, sz);
1013 }
1014 
1015 
1016 #include <sys/ioctl.h>
1017 #ifdef HAVE_SYS_FILIO_H
1018 #include <sys/filio.h>  /* FIONREAD (for illumos (OpenIndiana)) */
1019 #endif
1020 #ifdef _WIN32
1021 #include <winsock2.h>
1022 #endif
1023 int fdevent_ioctl_fionread (int fd, int fdfmt, int *toread) {
1024   #ifdef _WIN32
1025     if (fdfmt != S_IFSOCK) { errno = ENOTSOCK; return -1; }
1026     return ioctlsocket(fd, FIONREAD, toread);
1027   #else
1028    #ifdef __CYGWIN__
1029     /*(cygwin supports FIONREAD on pipes, not sockets)*/
1030     if (fdfmt != S_IFIFO) { errno = EOPNOTSUPP; return -1; }
1031    #else
1032     UNUSED(fdfmt);
1033    #endif
1034     return ioctl(fd, FIONREAD, toread);
1035   #endif
1036 }
1037 
1038 
1039 int fdevent_connect_status(int fd) {
1040     /* try to finish the connect() */
1041     /*(should be called after connect() only when fd is writable (POLLOUT))*/
1042     int opt;
1043     socklen_t len = sizeof(opt);
1044     return (0 == getsockopt(fd,SOL_SOCKET,SO_ERROR,&opt,&len)) ? opt : errno;
1045 }
1046 
1047 
1048 #include <netinet/tcp.h>
1049 #if (defined(__APPLE__) && defined(__MACH__)) \
1050   || defined(__FreeBSD__) || defined(__NetBSD__) \
1051   || defined(__OpenBSD__) || defined(__DragonFly__)
1052 #include <netinet/tcp_fsm.h>
1053 #endif
1054 
1055 /* fd must be TCP socket (AF_INET, AF_INET6), end-of-stream recv() 0 bytes */
1056 int fdevent_is_tcp_half_closed(int fd) {
1057   #ifdef TCP_CONNECTION_INFO     /* Darwin */
1058     struct tcp_connection_info tcpi;
1059     socklen_t tlen = sizeof(tcpi);
1060     return (0 == getsockopt(fd, IPPROTO_TCP, TCP_CONNECTION_INFO, &tcpi, &tlen)
1061             && tcpi.tcpi_state == TCPS_CLOSE_WAIT);
1062   #elif defined(TCP_INFO) && defined(TCPS_CLOSE_WAIT)
1063     /* FreeBSD, NetBSD (not present in OpenBSD or DragonFlyBSD) */
1064     struct tcp_info tcpi;
1065     socklen_t tlen = sizeof(tcpi);
1066     return (0 == getsockopt(fd, IPPROTO_TCP, TCP_INFO, &tcpi, &tlen)
1067             && tcpi.tcpi_state == TCPS_CLOSE_WAIT);
1068   #elif defined(TCP_INFO) && defined(__linux__)
1069     /* Linux (TCP_CLOSE_WAIT is enum, so can not #ifdef TCP_CLOSE_WAIT) */
1070     struct tcp_info tcpi;
1071     socklen_t tlen = sizeof(tcpi);/*SOL_TCP == IPPROTO_TCP*/
1072     return (0 == getsockopt(fd,     SOL_TCP, TCP_INFO, &tcpi, &tlen)
1073             && tcpi.tcpi_state == TCP_CLOSE_WAIT);
1074   #else
1075     UNUSED(fd);
1076     /*(0 != getpeername() error might indicate TCP RST, but success
1077      * would not differentiate between half-close and full-close)*/
1078     return 0; /* false (not half-closed) or TCP state unknown */
1079   #endif
1080 }
1081 
1082 
1083 int fdevent_set_tcp_nodelay (const int fd, const int opt)
1084 {
1085     return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
1086 }
1087 
1088 
1089 int fdevent_set_so_reuseaddr (const int fd, const int opt)
1090 {
1091     return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
1092 }
1093 
1094 
1095 #include <sys/stat.h>
1096 #include "safe_memclear.h"
1097 __attribute_cold__ /*(convenience routine for use at config at startup)*/
1098 char *
1099 fdevent_load_file (const char * const fn, off_t *lim, log_error_st *errh, void *(malloc_fn)(size_t), void(free_fn)(void *))
1100 {
1101     int fd = -1;
1102     off_t sz = 0;
1103     char *buf = NULL;
1104     do {
1105         fd = fdevent_open_cloexec(fn, 1, O_RDONLY, 0); /*(1: follows symlinks)*/
1106         if (fd < 0) break;
1107 
1108         struct stat st;
1109         if (0 != fstat(fd, &st)) break;
1110         if ((sizeof(off_t) > sizeof(size_t) && st.st_size >= (off_t)~(size_t)0u)
1111             || (*lim != 0 && st.st_size >= *lim)) {
1112             errno = EOVERFLOW;
1113             break;
1114         }
1115 
1116         sz = st.st_size;
1117         buf = malloc_fn((size_t)sz+1);/*+1 trailing '\0' for str funcs on data*/
1118         if (NULL == buf) break;
1119 
1120         if (sz) {
1121             ssize_t rd = 0;
1122             off_t off = 0;
1123             do {
1124                 rd = read(fd, buf+off, (size_t)(sz-off));
1125             } while (rd > 0 ? (off += rd) != sz : rd < 0 && errno == EINTR);
1126             if (off != sz) { /*(file truncated?)*/
1127                 if (rd >= 0) errno = EIO;
1128                 break;
1129             }
1130         }
1131 
1132         buf[sz] = '\0';
1133         *lim = sz;
1134         close(fd);
1135         return buf;
1136     } while (0);
1137     int errnum = errno;
1138     if (errh)
1139         log_perror(errh, __FILE__, __LINE__, "%s() %s", __func__, fn);
1140     if (fd >= 0) close(fd);
1141     if (buf) {
1142         safe_memclear(buf, (size_t)sz);
1143         free_fn(buf);
1144     }
1145     *lim = 0;
1146     errno = errnum;
1147     return NULL;
1148 }
1149 
1150 
1151 int
1152 fdevent_load_file_bytes (char * const buf, const off_t sz, off_t off, const char * const fn, log_error_st *errh)
1153 {
1154     int fd = -1;
1155     do {
1156         fd = fdevent_open_cloexec(fn, 1, O_RDONLY, 0); /*(1: follows symlinks)*/
1157         if (fd < 0) break;
1158 
1159         if (0 != off && (off_t)-1 == lseek(fd, off, SEEK_SET)) break;
1160         off = 0;
1161 
1162         ssize_t rd = 0;
1163         do {
1164             rd = read(fd, buf+off, (size_t)(sz-off));
1165         } while (rd > 0 ? (off += rd) != sz : rd < 0 && errno == EINTR);
1166         if (off != sz) { /*(file truncated? or incorrect sz requested)*/
1167             if (rd >= 0) errno = EIO;
1168             break;
1169         }
1170 
1171         close(fd);
1172         return 0;
1173     } while (0);
1174     int errnum = errno;
1175     if (errh)
1176         log_perror(errh, __FILE__, __LINE__, "%s() %s", __func__, fn);
1177     if (fd >= 0) close(fd);
1178     safe_memclear(buf, (size_t)sz);
1179     errno = errnum;
1180     return -1;
1181 }
1182