Index: usr.sbin/rpcbind/rpcb_svc_com.c =================================================================== --- usr.sbin/rpcbind/rpcb_svc_com.c +++ usr.sbin/rpcbind/rpcb_svc_com.c @@ -1101,7 +1101,7 @@ my_svc_run(void) { size_t nfds; - struct pollfd pollfds[FD_SETSIZE]; + struct pollfd pollfds[FD_SETSIZE + 1]; int poll_ret, check_ret; int n; #ifdef SVC_RUN_DEBUG @@ -1112,6 +1112,9 @@ for (;;) { p = pollfds; + p->fd = terminate_rfd; + p->events = MASKVAL; + p++; for (n = 0; n <= svc_maxfd; n++) { if (FD_ISSET(n, &svc_fdset)) { p->fd = n; @@ -1130,23 +1133,26 @@ fprintf(stderr, ">\n"); } #endif - switch (poll_ret = poll(pollfds, nfds, 30 * 1000)) { + poll_ret = poll(pollfds, nfds, 30 * 1000); + + if (doterminate != 0) { + close(rpcbindlockfd); +#ifdef WARMSTART + syslog(LOG_ERR, + "rpcbind terminating on signal %d. Restart with \"rpcbind -w\"", + (int)doterminate); + write_warmstart(); /* Dump yourself */ +#endif + exit(2); + } + + switch (poll_ret) { case -1: /* * We ignore all errors, continuing with the assumption * that it was set by the signal handlers (or any * other outside event) and not caused by poll(). */ - if (doterminate != 0) { - close(rpcbindlockfd); -#ifdef WARMSTART - syslog(LOG_ERR, - "rpcbind terminating on signal %d. Restart with \"rpcbind -w\"", - (int)doterminate); - write_warmstart(); /* Dump yourself */ -#endif - exit(2); - } case 0: cleanfds = svc_fdset; __svc_clean_idle(&cleanfds, 30, FALSE); Index: usr.sbin/rpcbind/rpcbind.h =================================================================== --- usr.sbin/rpcbind/rpcbind.h +++ usr.sbin/rpcbind/rpcbind.h @@ -70,6 +70,7 @@ extern int debugging; extern int doabort; +extern int terminate_rfd; extern volatile sig_atomic_t doterminate; #ifdef LIBWRAP extern int libwrap; Index: usr.sbin/rpcbind/rpcbind.c =================================================================== --- usr.sbin/rpcbind/rpcbind.c +++ usr.sbin/rpcbind/rpcbind.c @@ -79,6 +79,7 @@ /* Global variables */ int debugging = 0; /* Tell me what's going on */ int doabort = 0; /* When debugging, do an abort on errors */ +int terminate_rfd; /* Pipefd to wake on signal */ volatile sig_atomic_t doterminate = 0; /* Terminal signal received */ rpcblist_ptr list_rbl; /* A list of version 3/4 rpcbind services */ int rpcbindlockfd; @@ -101,6 +102,7 @@ static int ipv6_only = 0; static int nhosts = 0; static int on = 1; +static int terminate_wfd; #ifdef WARMSTART /* Local Variable */ @@ -133,6 +135,7 @@ void *nc_handle; /* Net config handle */ struct rlimit rl; int maxrec = RPC_MAXDATASIZE; + int error, fds[2]; parseargs(argc, argv); @@ -192,6 +195,16 @@ } endnetconfig(nc_handle); + /* + * Allocate pipe fd to wake main thread from signal handler in non-racy + * way. + */ + error = pipe(fds); + if (error != 0) + err(1, "pipe failed"); + terminate_rfd = fds[0]; + terminate_wfd = fds[1]; + /* catch the usual termination signals for graceful exit */ (void) signal(SIGCHLD, reap); (void) signal(SIGINT, terminate); @@ -761,8 +774,13 @@ static void terminate(int signum) { + char c = '\0'; + ssize_t wr; doterminate = signum; + wr = write(terminate_wfd, &c, 1); + if (wr < 1) + _exit(2); } void