Bug 4472

Summary: busybox tail -f does not terminate with SIGINT (Ctrl+c) via telnet
Product: Busybox Reporter: Steven Krebs <Steven.Krebs>
Component: NetworkingAssignee: unassigned
Status: RESOLVED WORKSFORME    
Severity: normal CC: busybox-cvs
Priority: P3    
Version: 1.16.x   
Target Milestone: ---   
Hardware: Other   
OS: Linux   
Host: Target:
Build:

Description Steven Krebs 2011-11-10 22:11:41 UTC
If tail -f <filename> is used on busybox 1.16.0 in a telnet session, then you want to stop it using ctrl+c it does not work.   (Ctrl+c does work if using UART console, and ctrl+c does work when using less in telnet to prove that my telnet client is configured correctly).

Workaround:  Press ctrl+z then use ps to find the PID and then kill -9
Comment 1 Steven Krebs 2011-11-18 21:57:57 UTC
Was able to add a work around to networking/telnetd.c in function make_new_session()

Addition of
    signal(SIGINT, SIG_DFL);

near line 330 seems to work.
Comment 2 Denys Vlasenko 2011-11-19 21:59:34 UTC
(In reply to comment #0)
> If tail -f <filename> is used on busybox 1.16.0 in a telnet session, then you
> want to stop it using ctrl+c it does not work.

Does Ctrl-C work for other applets started in the telnet session, such as bare "cat" from shell prompt?

> (Ctrl+c does work if using
> UART console, and ctrl+c does work when using less in telnet to prove that my
> telnet client is configured correctly).

busybox's less installs SIGINT handler. Therefore, it might be unaffected by bad SIG_IGN.

(In reply to comment #1)
> Was able to add a work around to networking/telnetd.c in function
> make_new_session()
> 
> Addition of
>     signal(SIGINT, SIG_DFL);
> 
> near line 330 seems to work.

If this helps, it means that SIGINT is set to SIG_IGN. Can you verify this by using this line instead?

      bb_error_msg("Prev INT handler:%p", signal(SIGINT, SIG_DFL));

If it will print "1", then the setting was SIG_IGN indeed.
If this is the case, we need to figure out where it was set.

telnetd does not change SIGINT handling. (Please check it with strace to be sure). It must be its parent process then. Where do you launch telnetd from?
Comment 3 Steven Krebs 2011-11-27 21:53:58 UTC
> Where do you launch telnetd from?

telnetd is launched from /etc/rc3.d/S009telnetd -> /etc/init.d/telnetd during initialization.
Comment 4 Denys Vlasenko 2011-11-28 03:00:01 UTC
I need answers to all of my questions, not just the last one.
Comment 5 Denys Vlasenko 2011-11-29 10:24:03 UTC
> Addition of
> >     signal(SIGINT, SIG_DFL);
> > 
> > near line 330 seems to work.
> 
> If this helps, it means that SIGINT is set to SIG_IGN. Can you verify this by
> using this line instead?
> 
>       bb_error_msg("Prev INT handler:%p", signal(SIGINT, SIG_DFL));
> 
> If it will print "1", then the setting was SIG_IGN indeed.
> If this is the case, we need to figure out where it was set.

This would be the most crucial test. If the printed value would be 1, then the parent process which starts telnetd is to blame: it sets SIGINT to SIG_IGN. Please find out which process is the parent, and where/why it sets SIGINT to be ignored.

In this case "signal(SIGINT, SIG_DFL)" is just a work-around: it's the parent process' responsibility to not mangle execution environment of the child. (For one, there are many more ways how parent can do bad things: it can mask signals, it can leave stray open file descriptors, etc.)
Comment 6 Steven Krebs 2011-11-29 15:56:26 UTC
Thank you for the analysis, will take a look at the parent process to see where if sets SIGINT to SIG_IGN
Comment 7 Denys Vlasenko 2012-01-10 17:12:25 UTC
Closing, since the problem appears to be external to tail. Reopen if you have new information.