Why does bash ignore SIGTERM?

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?

Asked By: Michał Šrajer

||

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

Answered By: Petr

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.

Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.