aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2021-06-05 15:24:04 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2021-06-05 15:24:04 +0200
commitd3e1090308b6d3c55e01a2000a743b73605ddd7f (patch)
tree57783b69d314c4b8998880ad6c38389989656782
parentac444861b0b0212803ef775c366c41c4c020b1f1 (diff)
downloadbusybox-w32-d3e1090308b6d3c55e01a2000a743b73605ddd7f.tar.gz
busybox-w32-d3e1090308b6d3c55e01a2000a743b73605ddd7f.tar.bz2
busybox-w32-d3e1090308b6d3c55e01a2000a743b73605ddd7f.zip
tcp/udpsvd: robustify SIGCHLD handling
function old new delta if_verbose_print_connection_status - 40 +40 tcpudpsvd_main 1798 1794 -4 connection_status 31 - -31 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 0/1 up/down: 40/-35) Total: 5 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/tcpudp.c33
-rw-r--r--runit/runsv.c5
2 files changed, 27 insertions, 11 deletions
diff --git a/networking/tcpudp.c b/networking/tcpudp.c
index 8c4afabf6..708e05c2e 100644
--- a/networking/tcpudp.c
+++ b/networking/tcpudp.c
@@ -216,17 +216,25 @@ enum {
216 OPT_K = (1 << 16), 216 OPT_K = (1 << 16),
217}; 217};
218 218
219static void connection_status(void) 219static void if_verbose_print_connection_status(void)
220{ 220{
221 /* "only 1 client max" desn't need this */ 221 if (verbose) {
222 if (cmax > 1) 222 /* "only 1 client max" desn't need this */
223 bb_error_msg("status %u/%u", cnum, cmax); 223 if (cmax > 1)
224 bb_error_msg("status %u/%u", cnum, cmax);
225 }
224} 226}
225 227
228/* SIGCHLD handler is reentrancy-safe because SIGCHLD is unmasked
229 * only over accept() or recvfrom() calls, not over memory allocations
230 * or printouts. Do need to save/restore errno in order not to mangle
231 * these syscalls' error code, if any.
232 */
226static void sig_child_handler(int sig UNUSED_PARAM) 233static void sig_child_handler(int sig UNUSED_PARAM)
227{ 234{
228 int wstat; 235 int wstat;
229 pid_t pid; 236 pid_t pid;
237 int sv_errno = errno;
230 238
231 while ((pid = wait_any_nohang(&wstat)) > 0) { 239 while ((pid = wait_any_nohang(&wstat)) > 0) {
232 if (max_per_host) 240 if (max_per_host)
@@ -236,8 +244,8 @@ static void sig_child_handler(int sig UNUSED_PARAM)
236 if (verbose) 244 if (verbose)
237 print_waitstat(pid, wstat); 245 print_waitstat(pid, wstat);
238 } 246 }
239 if (verbose) 247 if_verbose_print_connection_status();
240 connection_status(); 248 errno = sv_errno;
241} 249}
242 250
243int tcpudpsvd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 251int tcpudpsvd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -458,7 +466,7 @@ int tcpudpsvd_main(int argc UNUSED_PARAM, char **argv)
458 xconnect(0, &remote.u.sa, sa_len); 466 xconnect(0, &remote.u.sa, sa_len);
459 /* hole? at this point we have no wildcard udp socket... 467 /* hole? at this point we have no wildcard udp socket...
460 * can this cause clients to get "port unreachable" icmp? 468 * can this cause clients to get "port unreachable" icmp?
461 * Yup, time window is very small, but it exists (is it?) */ 469 * Yup, time window is very small, but it exists (does it?) */
462 /* ..."open new socket", continued */ 470 /* ..."open new socket", continued */
463 xbind(sock, &lsa->u.sa, sa_len); 471 xbind(sock, &lsa->u.sa, sa_len);
464 socket_want_pktinfo(sock); 472 socket_want_pktinfo(sock);
@@ -491,8 +499,7 @@ int tcpudpsvd_main(int argc UNUSED_PARAM, char **argv)
491 if (pid != 0) { 499 if (pid != 0) {
492 /* Parent */ 500 /* Parent */
493 cnum++; 501 cnum++;
494 if (verbose) 502 if_verbose_print_connection_status();
495 connection_status();
496 if (hccp) 503 if (hccp)
497 hccp->pid = pid; 504 hccp->pid = pid;
498 /* clean up changes done by vforked child */ 505 /* clean up changes done by vforked child */
@@ -586,8 +593,14 @@ int tcpudpsvd_main(int argc UNUSED_PARAM, char **argv)
586 593
587 xdup2(0, 1); 594 xdup2(0, 1);
588 595
596 /* Restore signal handling for the to-be-execed process */
589 signal(SIGPIPE, SIG_DFL); /* this one was SIG_IGNed */ 597 signal(SIGPIPE, SIG_DFL); /* this one was SIG_IGNed */
590 /* Non-ignored signals revert to SIG_DFL on exec anyway */ 598 /* Non-ignored signals revert to SIG_DFL on exec anyway
599 * But we can get signals BEFORE execvp(), this is unlikely
600 * but it would invoke sig_child_handler(), which would
601 * check waitpid(WNOHANG), then print "status N/M" if verbose.
602 * I guess we can live with that possibility.
603 */
591 /*signal(SIGCHLD, SIG_DFL);*/ 604 /*signal(SIGCHLD, SIG_DFL);*/
592 sig_unblock(SIGCHLD); 605 sig_unblock(SIGCHLD);
593 606
diff --git a/runit/runsv.c b/runit/runsv.c
index ecab8cdf5..61ea240ff 100644
--- a/runit/runsv.c
+++ b/runit/runsv.c
@@ -380,7 +380,10 @@ static void startservice(struct svdir *s)
380 xdup2(logpipe.wr, 1); 380 xdup2(logpipe.wr, 1);
381 } 381 }
382 } 382 }
383 /* Non-ignored signals revert to SIG_DFL on exec anyway */ 383 /* Non-ignored signals revert to SIG_DFL on exec anyway.
384 * But we can get signals BEFORE execl(), this is unlikely
385 * but wouldn't be good...
386 */
384 /*bb_signals(0 387 /*bb_signals(0
385 + (1 << SIGCHLD) 388 + (1 << SIGCHLD)
386 + (1 << SIGTERM) 389 + (1 << SIGTERM)