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