| 535 | |
| 536 | |
| 537 | void start_accept_loop(int port, int (*fn)(int, int)) |
| 538 | { |
| 539 | fd_set deffds; |
| 540 | int *sp, maxfd, i; |
| 541 | |
| 542 | #ifdef HAVE_SIGACTION |
| 543 | sigact.sa_flags = SA_NOCLDSTOP; |
| 544 | #endif |
| 545 | |
| 546 | /* open an incoming socket */ |
| 547 | sp = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint); |
| 548 | if (sp == NULL) |
| 549 | exit_cleanup(RERR_SOCKETIO); |
| 550 | |
| 551 | /* ready to listen */ |
| 552 | FD_ZERO(&deffds); |
| 553 | for (i = 0, maxfd = -1; sp[i] >= 0; i++) { |
| 554 | if (listen(sp[i], lp_listen_backlog()) < 0) { |
| 555 | rsyserr(FERROR, errno, "listen() on socket failed"); |
| 556 | #ifdef INET6 |
| 557 | if (errno == EADDRINUSE && i > 0) { |
| 558 | rprintf(FINFO, "Try using --ipv4 or --ipv6 to avoid this listen() error.\n"); |
| 559 | } |
| 560 | #endif |
| 561 | exit_cleanup(RERR_SOCKETIO); |
| 562 | } |
| 563 | FD_SET(sp[i], &deffds); |
| 564 | if (maxfd < sp[i]) |
| 565 | maxfd = sp[i]; |
| 566 | } |
| 567 | |
| 568 | /* now accept incoming connections - forking a new process |
| 569 | * for each incoming connection */ |
| 570 | while (1) { |
| 571 | fd_set fds; |
| 572 | pid_t pid; |
| 573 | int fd; |
| 574 | struct sockaddr_storage addr; |
| 575 | socklen_t addrlen = sizeof addr; |
| 576 | |
| 577 | /* close log file before the potentially very long select so |
| 578 | * file can be trimmed by another process instead of growing |
| 579 | * forever */ |
| 580 | logfile_close(); |
| 581 | |
| 582 | #ifdef FD_COPY |
| 583 | FD_COPY(&deffds, &fds); |
| 584 | #else |
| 585 | fds = deffds; |
| 586 | #endif |
| 587 | |
| 588 | if (select(maxfd + 1, &fds, NULL, NULL, NULL) < 1) |
| 589 | continue; |
| 590 | |
| 591 | for (i = 0, fd = -1; sp[i] >= 0; i++) { |
| 592 | if (FD_ISSET(sp[i], &fds)) { |
| 593 | fd = accept(sp[i], (struct sockaddr *)&addr, &addrlen); |
| 594 | break; |
no test coverage detected