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

signal handling, killing background processes started under sub-shells



#!/usr/local/bin/es
#
# This buggy code (I think the code is buggy, I make no claims that es
# is buggy) was abstracted out of fairly complex es code which manages
# background processes.  Normally, these background processes are
# killed after a timeout.  However, the user may send an interrupt
# signal to the outermost es process.  When the outermost es process
# is signaled, it should ensure that all children and below are killed
# before it exits completely.
#
# This code doesn't work as one might hope.  Since the background
# process_that_should_not_exit_until_killed is created by an es
# sub-shell, the signal handler can't kill it using the obvious code
# shown below.  Is there any way to ensure that an interrupt signal
# propagates to all background processes started in all sub-shells?
#
# I have found a number of workarounds which all involve forcing all
# background jobs to be started by the outermost es process.
#
# Note: this code does not appear to be buggy, if
#       '|[2] process_output' is removed (thus making the 'sleep 10'
#       and the background job direct children of the outermost
#       es process).
#
# Note: even though I note the code is buggy, when run it still doesn't
#       react as I might expect.  E.g. As shown, 'killed children' is
#       never printed when the outermost es process is sent the
#       interrupt signal.
#
# 0.9-alpha1, sunos-4.1.4
#
# Any comments on this issue welcome, but I expect I have just hit a
# murky area of es and will resign myself to staying away from complex
# background job situations... :-)

fn process_that_should_not_exit_until_killed {sleep 10000}
fn process_output {cat >/dev/null}

local (signals = $signals sighup sigint) \
{
  catch @ e {kill <=%apids >[2]/dev/null; echo killed children; throw $e} \
    {
      {
	process_that_should_not_exit_until_killed &

	# After timeout, kill background job (ensuring kill/wait is autonomous)
	sleep 10
	signals = $signals -sighup -sigint
	kill $apid
	wait
	signals = $signals sighup sigint
      } |[2] process_output
    }
}