diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-05 15:24:04 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-05 15:24:04 +0200 |
commit | d3e1090308b6d3c55e01a2000a743b73605ddd7f (patch) | |
tree | 57783b69d314c4b8998880ad6c38389989656782 | |
parent | ac444861b0b0212803ef775c366c41c4c020b1f1 (diff) | |
download | busybox-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.c | 33 | ||||
-rw-r--r-- | runit/runsv.c | 5 |
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 | ||
219 | static void connection_status(void) | 219 | static 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 | */ | ||
226 | static void sig_child_handler(int sig UNUSED_PARAM) | 233 | static 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 | ||
243 | int tcpudpsvd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 251 | int 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) |