0

In a bash shell in a terminal emulator window of lxterminal, I run

$ trap "echo hello" SIGHUP 
$ kill -s HUP $$
hello
$

and then I close the terminal emulator window.

Does closing the terminal emulator window only cause SIGHUP sent to the controlling process i.e. the bash process?

Since the SIGHUP trap doesn't terminate the bash process, I expect the bash process isn't terminated, but why is the bash process actually terminated?

Same thing happen if I change the trap to "" (ignore).

Terminal emulator matters. In bash running in a xterm window, setting trap to "" will make a xterm window not closable, while setting trap to echo hello can still close a xterm window.

Thanks.

Tim
  • 101,790

3 Answers3

6

[ I'll ignore the actual and possible behavior of different terminal emulators; a completely reasonable behavior would be to send a ^D (VEOF) to the pty on a window close / WM_DELETE_WINDOW, instead of tearing it down and causing the process running in it to receive a SIGHUP; the following assumes xterm, which will send a SIGHUP to the shell's process group in that case ].

The behavior you're seeing is because of the readline library, which is installing its own signal handlers. If you try the following:

xterm -e bash --noediting

(or dash, zsh or ksh instead of bash --noediting), then run

trap 'echo HUP' HUP

in the terminal, the window will become unclose-able; the shell will just print HUP as expected on trying to close the window; forcefully closing it (eg. with xkill) will cause the shell to exit with EIO errors, which is completely expected, since the pty was torn down.

Here is a simpler testcase for the behavior you're observing, not involving terminal emulators. Run the following in your terminal:

bash --rcfile <(echo 'trap "echo HUP" HUP')

Then kill -HUP $$ will just print HUP, but (sleep 1; kill -HUP $$) & (or kill -HUP <pid> from another window) will cause the shell to print exit and exit, unless you started it with --noediting (= don't use readline)

The readline() function as called by bash will install its own signal handlers upon waiting for input from the user, and restore the original handlers upon returning; a SIGHUP while waiting for input from the user will cause it to return NULL, which will be treated as EOF by bash (in the yy_readline_get() function), before having the chance to run the deferred trap handler.

  • Thanks. Is readline library a shared library? Does bash dynamically linked to it or dynamically load it by dlopen()? – Tim Jan 02 '19 at 02:31
  • Is closing a terminal window an event which can generate SIGHUP? If that were true, how can setting up SIGHUP handler prevent the terminal window from closing, given that the terminal window is already closed? – Tim Jan 02 '19 at 04:09
  • readline may be a shared lib, but on my system bash is linked statically to its own version of it 2. that's what xterm does when the user tries to close the window -- it sends a SIGHUP itself to process group of the terminal, and it won't actually destroy the window and the pty until the process started in it exits of its own volition.
  • –  Jan 02 '19 at 06:18
  • other terminal emulators like mlterm or lxterminal will just close the pty, which will cause the kernel to send a SIGHUP; but even if the shell running in the pty ignores or handles that sig, it will die with EIO errors when trying to read from, write to or do termios ioctls on the slave part of a pty with no master. –  Jan 02 '19 at 06:39