Sysop: | Amessyroom |
---|---|
Location: | Fayetteville, NC |
Users: | 43 |
Nodes: | 6 (0 / 6) |
Uptime: | 108:29:18 |
Calls: | 290 |
Files: | 905 |
Messages: | 76,683 |
You have a shell script that starts some background process with &.
Now you want to make sure that the background process terminates
when the shell script terminates.
Except... bash seems to block SIGINT for background processes. As
does FreeBSD's sh with both SIGINT and SIGQUIT. What now?
Is there a standard POSIX shell idiom to clean up background processes?
You have a shell script that starts some background process with &. Now
you want to make sure that the background process terminates when the
shell script terminates. In particular, when it terminates due to
special circumstances.
A noninteractive shell doesn't use job control, so the background
process shares the same process group. That's great! When somebody
hits ^C, SIGINT is sent to the whole process group. The same for ^\ and SIGQUIT, and for SIGHUP when the modem hangs up^W^W^Wxterm is closed.
So the background process will be terminated by default.
Except... bash seems to block SIGINT for background processes. As does FreeBSD's sh with both SIGINT and SIGQUIT. What now?
Also, the shell script is typically invoked from some implementation of make(1), which seems to add more complications.
This seems like a sufficiently common problem that there must be a
standard solution.
Is there a standard POSIX shell idiom to clean up background
processes?
You have a shell script that starts some background process with &.
Now you want to make sure that the background process terminates
when the shell script terminates. In particular, when it terminates
due to special circumstances.
On 2024-05-05, Christian Weisgerber <naddy@mips.inka.de> wrote:
Is there a standard POSIX shell idiom to clean up background
processes?
You have a shell script that starts some background process with &.
Now you want to make sure that the background process terminates
when the shell script terminates. In particular, when it terminates
due to special circumstances.
Maybe have an EXIT trap which calls wait?
In article <20240505214609.114@kylheku.com>,
Kaz Kylheku <643-408-1753@kylheku.com> wrote:
On 2024-05-05, Christian Weisgerber <naddy@mips.inka.de> wrote:
Is there a standard POSIX shell idiom to clean up background
processes?
You have a shell script that starts some background process with &.
Now you want to make sure that the background process terminates when
the shell script terminates. In particular, when it terminates due to
special circumstances.
Maybe have an EXIT trap which calls wait?
The fundamental underlying problem here is that the EXIT trap is only
called on a "normal" exit. In particular, it does not get called under
(at least) the following circumstances:
1) User hits ^C causing the script to abort.
2) Script exits via an "exec" statement.
As I read it, that's what this thread is actually about.
This is a problem I've often grappled with and I'm convinced that there
is no universal solution.
Having said that, I think we are all making our own assumptions about
what the actual, underlying problem is. Given that OP is not a newbie,
it would help a lot if he would clarify what exact situation he is
dealing with, rather than have us all guess (which is SOP when the
poster *is* a newbie).
On Mon, 6 May 2024 12:08:39 -0000 (UTC), gazelle@shell.xmission.com (Kenny McCormack) wrote in <v1ah87$l0a8$1@news.xmission.com>:
In article <20240505214609.114@kylheku.com>,
Kaz Kylheku <643-408-1753@kylheku.com> wrote:
On 2024-05-05, Christian Weisgerber <naddy@mips.inka.de> wrote:
Is there a standard POSIX shell idiom to clean up background
processes?
You have a shell script that starts some background process with &.
Now you want to make sure that the background process terminates when
the shell script terminates. In particular, when it terminates due to >>>> special circumstances.
Maybe have an EXIT trap which calls wait?
The fundamental underlying problem here is that the EXIT trap is only
called on a "normal" exit. In particular, it does not get called under
(at least) the following circumstances:
1) User hits ^C causing the script to abort.
I'm sorry, but I've waited and nobody said anything, so
I have to ask: Why couldn't you trap "kill -1 0" INT?
[...]
But the pseudo-signal 'EXIT' is non-standard (to my knowledge), so you
cannot generally rely on it, depending on your environment, and the OP
asked for a "standard POSIX shell idiom".
Janis Papanagnou wrote:
But the pseudo-signal 'EXIT' is non-standard (to my knowledge), so you
cannot generally rely on it, depending on your environment, and the OP
asked for a "standard POSIX shell idiom".
Quoting POSIX.2-1992, 3.14.13:
The condition can be EXIT; 0 (equivalent to EXIT); or a signal
specified using a symbolic name, without the SIG prefix, as listed
in Required Signals and Job Control Signals (Table 3-1 and Table 3-2
in POSIX.1 {8}). (For example: HUP, INT, QUIT, TERM). Setting a
trap for SIGKILL or SIGSTOP produces undefined results.
It has hardly changed in the current standard (POSIX.1-2017):
The condition can be EXIT, 0 (equivalent to EXIT), or a signal
specified using a symbolic name, without the SIG prefix, as listed
in the tables of signal names in the <signal.h> header defined in
XBD Chapter 13; for example, HUP, INT, QUIT, TERM. Implementations
may permit names with the SIG prefix or ignore case in signal
names as an extension. Setting a trap for SIGKILL or SIGSTOP
produces undefined results.
Having said that, I think we are all making our own assumptions about what the actual, underlying problem is. Given that OP is not a newbie, it would help a lot if he would clarify what exact situation he is dealing with, rather than have us all guess (which is SOP when the poster *is* a newbie).
I'm sorry, but I've waited and nobody said anything, so
I have to ask: Why couldn't you trap "kill -1 0" INT?
On 2024-05-06, Kenny McCormack <gazelle@shell.xmission.com> wrote:
Having said that, I think we are all making our own assumptions about what >> the actual, underlying problem is. Given that OP is not a newbie, it would >> help a lot if he would clarify what exact situation he is dealing with,
rather than have us all guess (which is SOP when the poster *is* a newbie).
As part of a regression test suite, somebody wrote something like
this in a script:
./http-server &
trap "kill %1" HUP INT QUIT PIPE TERM
sleep 1 # server starts up
[... Tests ...]
kill %1
wait %1 # wait for http-server
Using job control syntax in a non-interactive shell is already wrong, >although, to my surprise, it works as intended in common shells.
I've been looking at how to replace this with a portable-ish,
reliable-ish solution. An obvious step is to use a standard
background process reference $! instead of job control %1.
Less obvious is the question how to deal with signals that abort
the script, without leaving background processes hanging around.
On 2024-05-08, vallor <vallor@cultnix.org> wrote:
I'm sorry, but I've waited and nobody said anything, so
I have to ask: Why couldn't you trap "kill -1 0" INT?
There is the cosmetic problem that you'll get termination notices
referring to the new signal ("Hangup"), so I'll go with the less
confusing
trap "kill -TERM 0" INT
but yes, it may be as simple as that. Let me run some tests...
I have to ask: Why couldn't you trap "kill -1 0" INT?
trap "kill -TERM 0" INT
I don't get it. Is there any significant difference between hitting it with TERM vs. HUP?
Instead of
foo &
I can run
(trap - INT; exec foo) &
and indeed that seems to restore the default behavior, i.e., terminate
the process, for both FreeBSD sh and bash. Anybody see any problem
with that approach?
I'd also be interested in historical insights how this "ignore SIGINT
for asynchronous processes" behavior came to be.
BTW, I'm astonished about the "undefined results" for KILL/STOP. Yes,
on OS-level they cannot be caught but why undefined behavior on shell
level; what is the reason or practical rationale for that?