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() rename() */ 728 #include <signal.h> /* signal() */ 729 730 731 int fdevent_rename(const char *oldpath, const char *newpath) { 732 return rename(oldpath, newpath); 733 } 734 735 736 pid_t fdevent_fork_execve(const char *name, char *argv[], char *envp[], int fdin, int fdout, int fderr, int dfd) { 737 #ifdef HAVE_FORK 738 739 pid_t pid = fork(); 740 if (0 != pid) return pid; /* parent (pid > 0) or fork() error (-1 == pid) */ 741 742 /* child (0 == pid) */ 743 744 if (-1 != dfd) { 745 if (0 != fchdir(dfd)) 746 _exit(errno); 747 close(dfd); 748 } 749 750 if (0 != fdevent_set_stdin_stdout_stderr(fdin, fdout, fderr)) _exit(errno); 751 #ifndef FD_CLOEXEC 752 /*(might not be sufficient for open fds, but modern OS have FD_CLOEXEC)*/ 753 for (int i = 3; i < 256; ++i) close(i); 754 #endif 755 756 /* reset_signals which may have been ignored (SIG_IGN) */ 757 #ifdef SIGTTOU 758 signal(SIGTTOU, SIG_DFL); 759 #endif 760 #ifdef SIGTTIN 761 signal(SIGTTIN, SIG_DFL); 762 #endif 763 #ifdef SIGTSTP 764 signal(SIGTSTP, SIG_DFL); 765 #endif 766 signal(SIGPIPE, SIG_DFL); 767 768 execve(name, argv, envp ? envp : environ); 769 770 int errnum = errno; 771 if (0 == memcmp(argv[0], "/bin/sh", sizeof("/bin/sh")-1) 772 && argv[1] && 0 == memcmp(argv[1], "-c", sizeof("-c")-1)) 773 perror(argv[2]); 774 else 775 perror(argv[0]); 776 _exit(errnum); 777 778 #else 779 780 UNUSED(name); 781 UNUSED(argv); 782 UNUSED(envp); 783 UNUSED(fdin); 784 UNUSED(fdout); 785 UNUSED(fderr); 786 UNUSED(dfd); 787 return (pid_t)-1; 788 789 #endif 790 } 791 792 793 typedef struct fdevent_cmd_pipe { 794 pid_t pid; 795 int fds[2]; 796 const char *cmd; 797 time_t start; 798 } fdevent_cmd_pipe; 799 800 typedef struct fdevent_cmd_pipes { 801 fdevent_cmd_pipe *ptr; 802 uint32_t used; 803 uint32_t size; 804 } fdevent_cmd_pipes; 805 806 static fdevent_cmd_pipes cmd_pipes; 807 808 809 static pid_t fdevent_open_logger_pipe_spawn(const char *logger, int rfd) { 810 char *args[4]; 811 int devnull = fdevent_open_devnull(); 812 pid_t pid; 813 814 if (-1 == devnull) { 815 return -1; 816 } 817 818 *(const char **)&args[0] = "/bin/sh"; 819 *(const char **)&args[1] = "-c"; 820 *(const char **)&args[2] = logger; 821 args[3] = NULL; 822 823 pid = fdevent_fork_execve(args[0], args, NULL, rfd, devnull, devnull, -1); 824 825 if (pid > 0) { 826 close(devnull); 827 } 828 else { 829 int errnum = errno; 830 close(devnull); 831 errno = errnum; 832 } 833 return pid; 834 } 835 836 837 static void fdevent_restart_logger_pipe(fdevent_cmd_pipe *fcp, time_t ts) { 838 if (fcp->pid > 0) return; /* assert */ 839 if (fcp->start + 5 < ts) { /* limit restart to once every 5 sec */ 840 /* restart child process using existing pipe fds */ 841 fcp->start = ts; 842 fcp->pid = fdevent_open_logger_pipe_spawn(fcp->cmd, fcp->fds[0]); 843 } 844 } 845 846 847 void fdevent_restart_logger_pipes(time_t ts) { 848 for (uint32_t i = 0; i < cmd_pipes.used; ++i) { 849 fdevent_cmd_pipe * const fcp = cmd_pipes.ptr+i; 850 if (fcp->pid > 0) continue; 851 fdevent_restart_logger_pipe(fcp, ts); 852 } 853 } 854 855 856 int fdevent_waitpid_logger_pipe_pid(pid_t pid, time_t ts) { 857 for (uint32_t i = 0; i < cmd_pipes.used; ++i) { 858 fdevent_cmd_pipe * const fcp = cmd_pipes.ptr+i; 859 if (pid != fcp->pid) continue; 860 fcp->pid = -1; 861 fdevent_restart_logger_pipe(fcp, ts); 862 return 1; 863 } 864 return 0; 865 } 866 867 868 void fdevent_clr_logger_pipe_pids(void) { 869 for (uint32_t i = 0; i < cmd_pipes.used; ++i) { 870 fdevent_cmd_pipe *fcp = cmd_pipes.ptr+i; 871 fcp->pid = -1; 872 } 873 } 874 875 876 int fdevent_reaped_logger_pipe(pid_t pid) { 877 for (uint32_t i = 0; i < cmd_pipes.used; ++i) { 878 fdevent_cmd_pipe *fcp = cmd_pipes.ptr+i; 879 if (fcp->pid == pid) { 880 time_t ts = time(NULL); 881 if (fcp->start + 5 < ts) { /* limit restart to once every 5 sec */ 882 fcp->start = ts; 883 fcp->pid = fdevent_open_logger_pipe_spawn(fcp->cmd,fcp->fds[0]); 884 return (fcp->pid > 0) ? 1 : -1; 885 } 886 else { 887 fcp->pid = -1; 888 return -1; 889 } 890 } 891 } 892 return 0; 893 } 894 895 896 void fdevent_close_logger_pipes(void) { 897 for (uint32_t i = 0; i < cmd_pipes.used; ++i) { 898 fdevent_cmd_pipe *fcp = cmd_pipes.ptr+i; 899 close(fcp->fds[0]); 900 if (fcp->fds[1] != STDERR_FILENO) close(fcp->fds[1]); 901 } 902 free(cmd_pipes.ptr); 903 cmd_pipes.ptr = NULL; 904 cmd_pipes.used = 0; 905 cmd_pipes.size = 0; 906 } 907 908 909 void fdevent_breakagelog_logger_pipe(int fd) { 910 for (uint32_t i = 0; i < cmd_pipes.used; ++i) { 911 fdevent_cmd_pipe *fcp = cmd_pipes.ptr+i; 912 if (fcp->fds[1] != fd) continue; 913 fcp->fds[1] = STDERR_FILENO; 914 break; 915 } 916 } 917 918 919 static void fdevent_init_logger_pipe(const char *cmd, int fds[2], pid_t pid) { 920 fdevent_cmd_pipe *fcp; 921 if (cmd_pipes.used == cmd_pipes.size) { 922 cmd_pipes.size += 4; 923 cmd_pipes.ptr = 924 realloc(cmd_pipes.ptr, cmd_pipes.size * sizeof(fdevent_cmd_pipe)); 925 force_assert(cmd_pipes.ptr); 926 } 927 fcp = cmd_pipes.ptr + cmd_pipes.used++; 928 fcp->cmd = cmd; /* note: cmd must persist in memory (or else copy here) */ 929 fcp->fds[0] = fds[0]; 930 fcp->fds[1] = fds[1]; 931 fcp->pid = pid; 932 fcp->start = time(NULL); 933 } 934 935 936 static int fdevent_open_logger_pipe(const char *logger) { 937 int fds[2]; 938 pid_t pid; 939 if (pipe(fds)) { 940 return -1; 941 } 942 fdevent_setfd_cloexec(fds[0]); 943 fdevent_setfd_cloexec(fds[1]); 944 /*(nonblocking write() from lighttpd)*/ 945 if (0 != fdevent_fcntl_set_nb(fds[1])) { /*(ignore)*/ } 946 947 pid = fdevent_open_logger_pipe_spawn(logger, fds[0]); 948 949 if (pid > 0) { 950 fdevent_init_logger_pipe(logger, fds, pid); 951 return fds[1]; 952 } 953 else { 954 int errnum = errno; 955 close(fds[0]); 956 close(fds[1]); 957 errno = errnum; 958 return -1; 959 } 960 } 961 962 963 int fdevent_open_logger(const char *logger) { 964 if (logger[0] != '|') { /*(permit symlinks)*/ 965 int flags = O_APPEND | O_WRONLY | O_CREAT; 966 return fdevent_open_cloexec(logger, 1, flags, 0644); 967 } 968 else { 969 return fdevent_open_logger_pipe(logger+1); /*(skip the '|')*/ 970 } 971 } 972 973 int fdevent_cycle_logger(const char *logger, int *curfd) { 974 if (logger[0] != '|') { 975 int fd = fdevent_open_logger(logger); 976 if (-1 == fd) return -1; /*(error; leave *curfd as-is)*/ 977 if (-1 != *curfd) close(*curfd); 978 *curfd = fd; 979 } 980 return *curfd; 981 } 982 983 984 #ifndef MSG_DONTWAIT 985 #define MSG_DONTWAIT 0 986 #endif 987 #ifndef MSG_NOSIGNAL 988 #define MSG_NOSIGNAL 0 989 #endif 990 991 992 ssize_t fdevent_socket_read_discard (int fd, char *buf, size_t sz, int family, int so_type) { 993 #if defined(MSG_TRUNC) && defined(__linux__) 994 if ((family == AF_INET || family == AF_INET6) && so_type == SOCK_STREAM) { 995 ssize_t len = recv(fd, buf, sz, MSG_TRUNC|MSG_DONTWAIT|MSG_NOSIGNAL); 996 if (len >= 0 || errno != EINVAL) return len; 997 } 998 #else 999 UNUSED(family); 1000 UNUSED(so_type); 1001 #endif 1002 return read(fd, buf, sz); 1003 } 1004 1005 1006 #include <sys/ioctl.h> 1007 #ifdef HAVE_SYS_FILIO_H 1008 #include <sys/filio.h> /* FIONREAD (for illumos (OpenIndiana)) */ 1009 #endif 1010 #ifdef _WIN32 1011 #include <winsock2.h> 1012 #endif 1013 int fdevent_ioctl_fionread (int fd, int fdfmt, int *toread) { 1014 #ifdef _WIN32 1015 if (fdfmt != S_IFSOCK) { errno = ENOTSOCK; return -1; } 1016 return ioctlsocket(fd, FIONREAD, toread); 1017 #else 1018 #ifdef __CYGWIN__ 1019 /*(cygwin supports FIONREAD on pipes, not sockets)*/ 1020 if (fdfmt != S_IFIFO) { errno = EOPNOTSUPP; return -1; } 1021 #else 1022 UNUSED(fdfmt); 1023 #endif 1024 return ioctl(fd, FIONREAD, toread); 1025 #endif 1026 } 1027 1028 1029 int fdevent_connect_status(int fd) { 1030 /* try to finish the connect() */ 1031 /*(should be called after connect() only when fd is writable (POLLOUT))*/ 1032 int opt; 1033 socklen_t len = sizeof(opt); 1034 return (0 == getsockopt(fd,SOL_SOCKET,SO_ERROR,&opt,&len)) ? opt : errno; 1035 } 1036 1037 1038 #include <netinet/tcp.h> 1039 #if (defined(__APPLE__) && defined(__MACH__)) \ 1040 || defined(__FreeBSD__) || defined(__NetBSD__) \ 1041 || defined(__OpenBSD__) || defined(__DragonFly__) 1042 #include <netinet/tcp_fsm.h> 1043 #endif 1044 1045 /* fd must be TCP socket (AF_INET, AF_INET6), end-of-stream recv() 0 bytes */ 1046 int fdevent_is_tcp_half_closed(int fd) { 1047 #ifdef TCP_CONNECTION_INFO /* Darwin */ 1048 struct tcp_connection_info tcpi; 1049 socklen_t tlen = sizeof(tcpi); 1050 return (0 == getsockopt(fd, IPPROTO_TCP, TCP_CONNECTION_INFO, &tcpi, &tlen) 1051 && tcpi.tcpi_state == TCPS_CLOSE_WAIT); 1052 #elif defined(TCP_INFO) && defined(TCPS_CLOSE_WAIT) 1053 /* FreeBSD, NetBSD (not present in OpenBSD or DragonFlyBSD) */ 1054 struct tcp_info tcpi; 1055 socklen_t tlen = sizeof(tcpi); 1056 return (0 == getsockopt(fd, IPPROTO_TCP, TCP_INFO, &tcpi, &tlen) 1057 && tcpi.tcpi_state == TCPS_CLOSE_WAIT); 1058 #elif defined(TCP_INFO) && defined(__linux__) 1059 /* Linux (TCP_CLOSE_WAIT is enum, so can not #ifdef TCP_CLOSE_WAIT) */ 1060 struct tcp_info tcpi; 1061 socklen_t tlen = sizeof(tcpi);/*SOL_TCP == IPPROTO_TCP*/ 1062 return (0 == getsockopt(fd, SOL_TCP, TCP_INFO, &tcpi, &tlen) 1063 && tcpi.tcpi_state == TCP_CLOSE_WAIT); 1064 #else 1065 UNUSED(fd); 1066 /*(0 != getpeername() error might indicate TCP RST, but success 1067 * would not differentiate between half-close and full-close)*/ 1068 return 0; /* false (not half-closed) or TCP state unknown */ 1069 #endif 1070 } 1071 1072 1073 int fdevent_set_tcp_nodelay (const int fd, const int opt) 1074 { 1075 return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); 1076 } 1077 1078 1079 int fdevent_set_so_reuseaddr (const int fd, const int opt) 1080 { 1081 return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); 1082 } 1083 1084 1085 #include <sys/stat.h> 1086 #include "safe_memclear.h" 1087 __attribute_cold__ /*(convenience routine for use at config at startup)*/ 1088 char * 1089 fdevent_load_file (const char * const fn, off_t *lim, log_error_st *errh, void *(malloc_fn)(size_t), void(free_fn)(void *)) 1090 { 1091 int fd = -1; 1092 off_t sz = 0; 1093 char *buf = NULL; 1094 do { 1095 fd = fdevent_open_cloexec(fn, 1, O_RDONLY, 0); /*(1: follows symlinks)*/ 1096 if (fd < 0) break; 1097 1098 struct stat st; 1099 if (0 != fstat(fd, &st)) break; 1100 if ((sizeof(off_t) > sizeof(size_t) && st.st_size >= (off_t)~(size_t)0u) 1101 || (*lim != 0 && st.st_size >= *lim)) { 1102 errno = EOVERFLOW; 1103 break; 1104 } 1105 1106 sz = st.st_size; 1107 buf = malloc_fn((size_t)sz+1);/*+1 trailing '\0' for str funcs on data*/ 1108 if (NULL == buf) break; 1109 1110 if (sz) { 1111 ssize_t rd = 0; 1112 off_t off = 0; 1113 do { 1114 rd = read(fd, buf+off, (size_t)(sz-off)); 1115 } while (rd > 0 ? (off += rd) != sz : errno == EINTR); 1116 if (off != sz) { /*(file truncated?)*/ 1117 if (rd >= 0) errno = EIO; 1118 break; 1119 } 1120 } 1121 1122 buf[sz] = '\0'; 1123 *lim = sz; 1124 close(fd); 1125 return buf; 1126 } while (0); 1127 int errnum = errno; 1128 if (errh) 1129 log_perror(errh, __FILE__, __LINE__, "%s() %s", __func__, fn); 1130 if (fd >= 0) close(fd); 1131 if (buf) { 1132 safe_memclear(buf, (size_t)sz); 1133 free_fn(buf); 1134 } 1135 *lim = 0; 1136 errno = errnum; 1137 return NULL; 1138 } 1139