Bug 59029
| Summary: | in.telnetd creating runaway processes upon closing | ||
|---|---|---|---|
| Product: | [Retired] Red Hat Linux | Reporter: | Need Real Name <jmcelroy> |
| Component: | util-linux | Assignee: | Elliot Lee <sopwith> |
| Status: | CLOSED RAWHIDE | QA Contact: | Ben Levenson <benl> |
| Severity: | medium | Docs Contact: | |
| Priority: | medium | ||
| Version: | 7.2 | CC: | ewt, harald, matthew_wygant, tao |
| Target Milestone: | --- | ||
| Target Release: | --- | ||
| Hardware: | i686 | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | Doc Type: | Bug Fix | |
| Doc Text: | Story Points: | --- | |
| Clone Of: | Environment: | ||
| Last Closed: | 2002-03-08 19:03:32 UTC | Type: | --- |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
| Bug Depends On: | |||
| Bug Blocks: | 86557 | ||
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. *** |
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.