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