Ash + telnetd: telnet client hangs after exit

Ralf Friedl Ralf.Friedl at online.de
Mon Nov 5 11:55:55 UTC 2007


Hi

I found some more problems with the current telnetd code (I'm sorry that 
I didn't notice them earlier).

The bigger problem is that without the option -K, telnetd will never 
wait for its children, leaving them as zombies.

A minor problem is that it is possible, although unlikely, that two 
children exit at the same time. Or more exactly, it is possible that one 
child exits, which raises SIGCHLD for telnetd. If another child exits 
after the first, but before the signal was delivered, the signal handler 
will be called only once, not twice for the two children.
If the system is heavy loaded, maybe parts of telnetd paged out, this 
time may be log enough for this to happen.
It is unlikely to happen with telnetd, but I already had this problem 
with a mail server in real life. The solution is to loop in the signal 
handler until wait finds no more children.

I also changed the argument to waitpid from &sig to NULL because "man 
waitpid" says: "If status is not NULL, wait or waitpid store ...", 
because the status is not used.

Regards
Ralf Friedl


--- networking/telnetd.c
+++ networking/telnetd.c
@@ -384,13 +384,17 @@
        pid_t pid;
        struct tsession *ts;

-       pid = waitpid(-1, &sig, WNOHANG);
-       if (pid > 0) {
+       for (;;) {
+               pid = waitpid(-1, NULL, WNOHANG);
+               if (pid <= 0)
+                       break;
+               if (!(option_mask32 & OPT_WATCHCHILD))
+                       continue;
                ts = sessions;
                while (ts) {
                        if (ts->shell_pid == pid) {
                                ts->shell_pid = -1;
-                               return;
+                               break;
                        }
                        ts = ts->next;
                }
@@ -464,8 +468,7 @@
        /* We don't want to die if just one session is broken */
        signal(SIGPIPE, SIG_IGN);

-       if (opt & OPT_WATCHCHILD)
-               signal(SIGCHLD, handle_sigchld);
+       signal(SIGCHLD, handle_sigchld);

 /*
    This is how the buffers are used. The arrows indicate the movement




More information about the busybox mailing list