help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-bash] What the signals cause EXIT?


From: Paul Wagner
Subject: Re: [Help-bash] What the signals cause EXIT?
Date: Mon, 19 Nov 2018 10:46:50 +0100
User-agent: Posteo Webmail

Dear Bob,

thanks a lot for explaining all those signalling details. As someone who is having troubles with a pipeline and SIGPIPE (as posted a few weeks ago here) myself, could you point to resources explaining the whole *nix signalling infrastructure?

Thanks for your help,

Paul

On 18.11.2018 01:26, Bob Proulx wrote:
Peng Yu wrote:
It seems that
- SIGKILL directly kill the process without triggering EXIT.

SIGKILL is a very special type of signal.  It really isn't a signal at
all.  What it does is cause the kernel to remove the process from the
run queue.  Which means that the process does not receive a signal and
can never receive the signal and can never trap the signal.  No signal
handling can be done by the process, ever.  It can't log about it,
ever.  The process simply stops running.

Which is why it is always bad to kill a process using SIGKILL that you
are not the developer of because you don't know if there are temporary
files or other state that needs to be cleaned up manually.  It is
truly an action of last resort to be used only when all else fails
followed by rebooting the system because something must be terribly
broken to have gotten into that need for such a last resort.

- SIGCHLD does not trigger EXIT.

As documented the default action for SIGCHLD is to ignore it.  As with
most things it has a purpose and it is not general but very specific.

- SIGINT and SIGQUIT are ignored as they are not sent from the same
terminal.

There appears to be confusion surrounding foreground process groups.

When bash invokes sleep there are then two processes running in the
foreground process group.  When the tty driver sees Control-C (see
'stty -a' for intr = ^C) then it sends the foreground process group an
interrupt with SIGINT.  Both the shell and the sleep process are in
the foreground process group and receive the SIGINT.  As per signal(7)
documentation the default action is to terminate therefore the sleep
process terminates.  The bash process has trapped SIGINT and therefore
invokes the logical EXIT trap just before exiting.

If you are sending a SIGINT to the bash (via $$) process then *only*
the bash process is receiving the signal.  The sleep process was not
sent the signal, does not receive it, and sleeps for the duration when
it exits normally.

For your testing I think you should be sending to the foreground
process group.

  man kill

   Negative PID values may be used to choose whole process groups; see
   the PGID column in ps command output.

Sending 'kill -s SIGINT -$pid' will send to the process group.
(Note that dash's builtin kill does not handle this syntax.)

So, other than these signals, all the rest signals cause EXIT. Is my
conclusion correct? Some of the conclusion is counter-intuitive.

Bash automatically traps signals that cause the process to exit, see
man 7 signal, and therefore the EXIT trap runs.  Other shells such as
POSIX shells such as dash do not do this.  In POSIX shells if you want
to trap a signal such that the logical EXIT trap is invoked then this
must be coded up with a trap handler explicitly.

My recommendation is to only ever care about HUP, INT, QUIT, and TERM
for cleanup actions.  Sometimes, rarely, there may be a special
purpose use of SIGUSR1 and/or SIGUSR2.  (And in very, very, very rare
cases PIPE but special care must be taken when dealing with SIGPIPE to
avoid an infinite stack overflow condition.  You have been warned.)

Trapping other signals is a sign of a program design problem.

Bash traps signals for you automatically and will run the logical EXIT
trap but POSIX shells do not.  That is one reason I believe it is
always a good idea to code them explicitly so that they will work
portably across shells other than bash too.  But regardless of that if
trapping signals then I like to see a diagnostic message printed in
the case of a signal and that requires explicitly trapping them.

For example, what is the reason to EXIT when SIGWINCH is triggered?

What makes you think bash exits when receiving SIGWINCH?  Double check
your test case.

Could anybody let me know what signals will result in EXIT? Thanks.
> signal(7)
> man 7 signal

I don't quite understand signal(7) with respect to bash. For example,

Why are there three values for SIGUSR1 in singal(7), whereas there are
only 30 for SIGUSR1 in bash?

       SIGUSR1   30,10,16    Term    User-defined signal 1

In man 7 signal:

(Where three values are given, the first one is usually valid for alpha and sparc, the middle one for x86, arm, and most other architectures, and the last one for mips. (Values for parisc are not shown; see the Linux kernel source for signal numbering on that architecture.) A dash (-) denotes that a signal is absent on the corresponding architecture.

What the Core is in bash?

       SIGQUIT       3       Core    Quit from keyboard

The idea behind SIGQUIT invoked from the tty driver via Control-\ is
that a developer authoring a C program can cause a program in an
infinite loop to dump a core (memory used to be ferrite core at the
time) image to disk in a file named "core" and kill the program.  Then
the developer can start the debugger on the source code referencing
the core file and see what the program counter is pointing at and dump
the value of variables and registers.  This is usually enough to
determine why a program was in an infinite loop and fix it.

These days core dumps are almost always disabled (ulimit -c) by
default.  That means that for most non-developers these days
triggering SIGQUIT with Control-\ is simply another signal that should
terminate the program.  Bash itself shouldn't dump a core image
because that wouldn't help in debugging the shell script as it is only
indirectly associated.  Your shell script program might choose to dump
some type of program state for debugging purposes when trapping
SIGQUIT however.  I haven't seen that technique used much though and
can't recommend it as better debugging techniques exist.

Why SIGTTIN leads to EXIT?

SIGTTIN 21,21,26 Stop Terminal input for background process

SIGTTIN leads to job control stopping the program not exiting.  If you
continue the program then eventually when it exists the logical EXIT
trap will be invoked.

This is a complex area with subtle interactions.  I may have made a
mistake in the above description.  It was written with the best of
intentions though.

Bob



reply via email to

[Prev in Thread] Current Thread [Next in Thread]