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