11

Sometimes when I want to logout quickly I do kill -15 -1. I've noticed that bash is ignoring SIGTERM.

I wonder what's the rationale for such bash behavior?

It's not very UNIX'y to ignore SIGTERM without a good reason, isn't it?

UPDATE:

same (no)effect for all:

$ kill -TERM $$
$ type kill
kill is a shell builtin
$ command kill -TERM $$
$ /bin/kill -TERM $$

UPDATE2:

From man bash:

When bash is interactive, in the absence of any traps, it ignores SIGTERM

So it's done on purpose. But why?

8
  • Which kill are you using? /bin/kill or the shell builtin? If the latter, I'm guessing that the shell won't kill itself with its own builtin. – terdon Feb 20 '15 at 11:59
  • @terdon: I used builtin, but I don't think that's the reason to not to kill it self. – Michał Šrajer Feb 20 '15 at 12:14
  • 1
    If you want to logout quickly then use Ctrl+d – YoMismo Feb 20 '15 at 13:12
  • 1
    @YoMismo: "logout from X session" – Michał Šrajer Feb 20 '15 at 14:35
  • 2
    @MichałŠrajer: Ctrl-Alt-Backspace does this for me on Xorg... you might have to enable it in xorg.conf, though. – Laszlo Valko Feb 21 '15 at 3:46
11

First, this isn't specific to bash. ATT ksh, dash and zsh behave the same way: they ignore SIGTERM and SIGQUIT during command line edition; as for mksh, it also doesn't quit but treats them like SIGINT.

Both the ksh manual and the bash manual justify ignoring SIGTERM in these terms:

so that kill 0 does not kill an interactive shell

kill 0 kills all processes in the process group that the shell is in¹. In a nutshell, the process group consists of all the processes running in the foreground on a terminal, or all the processes in a background or suspended job.

More precisely, this is what happens in modern shells with job control. In such shells, kill 0 wouldn't be useful, as the shell would be in a process group of its own. Older shells (or modern shells after set +m) did not create process groups for background commands. So you could use the command kill 0 to kill all background commands without getting logged out.² Thus the kill 0 rationale looks like an old one which is no longer justified nowadays but kept for backward compatibility.

However there are other similar situations where making the shell immune is useful. Consider the case where you have processes hogging a terminal and you want to kill them without getting logged out. Many systems have a tool like pkill which let you kill the processes running on a terminal. You can run pkill -t $TTY or pkill -QUIT -t $TTY to kill all processes that are running on the current terminal, except the shell which ignores the signal.

A shell normally goes away either when the user exits it (with a command like exit or logout), or when its terminal signals the end of the input (the user can cause this by pressing Ctrl+D) or goes away altogether. In this last case, the shell receives the signal SIGHUP, and it doesn't ignore that one.

For your use case of logging out of an X session, kill -15 -1 will do it, since it kills the terminal emulator which causes the shell to receive SIGHUP. It's in fact enough to kill the X server, but that requires finding its process ID. If you want the same command to work on a text session, you can use kill -15 -1; exit. That's quite a dangerous command to have at your fingertips anyway.

¹ This doesn't seem to be mentioned in shell manuals as a rule; it's a feature of the underlying system call. It is mentioned explicitly in the POSIX specification.
² Nowadays, to do that, run jobs -l to see a list of jobs with their process group ID, then kill -123 -456 … to kill the process groups.

5

This might answer your question:

When Bash is interactive, in the absence of any traps, it ignores SIGTERM (so that ‘kill 0’ does not kill an interactive shell), and SIGINT is caught and handled (so that the wait builtin is interruptible). When Bash receives a SIGINT, it breaks out of any executing loops. In all cases, Bash ignores SIGQUIT. If job control is in effect (see Job Control), Bash ignores SIGTTIN, SIGTTOU, and SIGTSTP.

Non-builtin commands started by Bash have signal handlers set to the values inherited by the shell from its parent. When job control is not in effect, asynchronous commands ignore SIGINT and SIGQUIT in addition to these inherited handlers. Commands run as a result of command substitution ignore the keyboard-generated job control signals SIGTTIN, SIGTTOU, and SIGTSTP.

The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP. To prevent the shell from sending the SIGHUP signal to a particular job, it should be removed from the jobs table with the disown builtin (see Job Control Builtins) or marked to not receive SIGHUP using disown -h.

If the huponexit shell option has been set with shopt (see The Shopt Builtin), Bash sends a SIGHUP to all jobs when an interactive login shell exits.

If Bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes. When Bash is waiting for an asynchronous command via the wait builtin, the reception of a signal for which a trap has been set will cause the wait builtin to return immediately with an exit status greater than 128, immediately after which the trap is executed.

SOURCE: The GNU Bash manual

1
  • I quoted this in my update2. Man states that bash is doing so, but does not explain why such decision. The question remains - why? – Michał Šrajer Feb 20 '15 at 14:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.