From Bugzilla Helper: User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.7) Gecko/20011226 Description of problem: when a telnet client is killed, the telnet server does not kill a child process which is sleeping in a select() call Version-Release number of selected component (if applicable): How reproducible: Always Steps to Reproduce: 1. Compile the following with gcc. This program just calls select() every 5 seconds. #include <stdio.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> int main(int argc, char *argv[]) { fd_set rfds; struct timeval tv; while (1) { FD_ZERO(&rfds); FD_SET(0, &rfds); tv.tv_sec = 5; tv.tv_usec = 0; select(1, &rfds, NULL, NULL, &tv); } return 0; } 2. With the telnet server enabled, do a 'xterm -e telnet localhost' and login. 3. In the new xterm window, start the program compiled in step 1. 4. kill the new xterm window 5. run top/ps and see the runaway process in an endless loop Actual Results: The sample program that was run from within the telnet session will not be killed. It will take up 100% of the cpu on a single cpu box. Expected Results: The sample program should have been killed Additional info: This problem is not seen when using ssh or when starting the sample program directly.
The pipe was closed... stating the german man page :) man 2 select Nachdem der einzige Schreiber eine named Pipe schlie_t, wird select() zur|ckkehren und angeben, da_ etwas von der Pipe gelesen werden kann. Wenn dann von dieser gelesen wird, wird read(2) 0 zur|ckliefern, was das Dateiende markiert. Code, der annimmt, da_ select() blockiert, sollte die Pipe mit O_RDWR statt O_RDONLY vffnen. After the only writer closed a named pipe, select() will return and indicate that s.th. from the pipe can be read. If you read from the pipe, read(2) will return 0, which indicates the end of file. Code, which wants that select() blocks should open the pipe with O_RDWR instead of O_RDONLY.
The sample program was running select() on stdin. Are you saying that to avoid this problem, a programmer must close and reopen stdin before attempting to to use a select() on it ?!? This is not a satisfactory solution.
i am saying that stdin has EOF and cannot be reopened (no more terminal)
I see your point. Where we are seeing this issue is inside the runtime of rmcobol. The sample program was made by examining 'strace' logs (I believe that in the logs there is read on stdin following the select). Apparently rmcobol is not looking for an end of file condition on stdin. Is the sample program not receiving a signal upon the death of it's parent? Is it ignoring it?
I took a closer look. I followed the instructions in the initial post I got the following processes $ps axj PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 739 5351 5351 5351 ? -1 S 0 0:00 in.telnetd: jm-linux 5351 5352 5352 5352 pts/1 5401 S 0 0:00 login -- jmcelro9 5352 5353 5353 5352 pts/1 5401 S 11277 0:00 -bash 5353 5401 5401 5352 pts/1 5401 R 11277 0:19 ./go2 When a session leader exits (in this case login) a SIGHUP is supposed to be sent to all the processes in it session. This is what I expected to happen. What appears to be happening is when telnetd dies, it is not signally its child 'login' process. Because the login process is not dying, none of the processes in its session are being sent the expect SIGHUP. hence the following: $ps axj PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 1 5352 5352 5352 ? -1 S 0 0:00 login -- jmcelro9 5352 5353 5353 5352 ? -1 S 11277 0:00 -bash 5353 5401 5401 5352 ? -1 R 11277 8:03 ./go2 If you replace the program in the initial post with one that does not check stdin, you will run into same circumstance. For instance the following code will have the same problem: int main(int argc, char *argv[]) { while(1) { } return 0; } as will the shell script 'while [ 1 ]; do a=$((a+1)); done' Basically it looks like any non interactive program will continue to run after the telnet session closes.
ok, here is the problem: - telnetd exits - kernel sends SIGHUP to terminal sessions leader - login has forked itsself because of PAM - the parent login process ignores SIGHUP - the child login (now bash) does not get SIGHUP --> login and bash stay alive after telnetd exists problem is in util-linux-2.11n-5 login.c(1135): } else if (childPid) { /* parent - wait for child to finish, then cleanup session */ /* ioctl(0, TIOCNOTTY, NULL); */ signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGTERM, SIG_IGN); wait(NULL); PAM_END; exit(0); } solution: - catch the signal and kill(childPid, SIGHUP) - or make the child the session leader (setsid())
*** Bug 59411 has been marked as a duplicate of this bug. ***
As per #54741, this is fixed in util-linux-2.11n-8
*** Bug 62518 has been marked as a duplicate of this bug. ***
*** Bug 89653 has been marked as a duplicate of this bug. ***