I am trying to implement a timeout for a big script which calls a lot of external process.
I start a separate process as a watchdog that checks every second if the timeout is reached
(
PARENT_PID=$$
((t = 2 ))
while ((t > 0)); do
sleep 1
((t -= 1))
done
kill -s ALRM ${PARENT_PID} 2> /dev/null
) &
And then I trap the ALRM
signal in the main script
trap critical ALRM
and finally in the critical function I print out some text and exit the program cleanly
Now the problem
- if the timeout occurs while $PARENT_PID is running everything works as expected
- if the timeout occurs while a child process is running (e.g., I call openssl and openssl is running) nothing happens. If I terminate the running child process (e.g. by pressing CRTL+C) the parent process trap is activated and everything continues as expected
How can I fix the problem? So that the trap in the parent process is called and I can terminate the whole?
Update
If the watchdog kills with -KILL
the parent process, the process with all the child processed are terminated as expected
The problem is that I would like to intercept the timeout and generate some output. For this reason I use the ALRM signal.
The KILL
signal cannot be ignored while the ALRM
one can.
My idea at the moment is the following:
- the parent process has a trap for the alarm
- the child process ignores the alarm signal
- when the signal is sent to the parent the child process is running and the parent is in the background
- my process is waken up when the child is terminated
If this is correct my idea will never work.
To make it work I should for each child process
- start it in the background
- wait for it and continue
So that the parent process will be able to trap the signal
Am I correct?
Update 2
A reduced example
critical() {
printf "whathever\n"
WATCHDOG_PID=$!
kill -TERM $WATCHDOG_PID
}
(
PARENT_PID=$$
((t = "${TIMEOUT}" ))
while ((t > 0)); do
sleep 1
((t -= 1))
done
kill -s ALRM ${PARENT_PID} 2> /dev/null
) &
trap critical ALRM
# an example of a long running command
(echo 'Q' | openssl s_client -connect corti.li:imap -servername corti.li -verify 6 ) &
wait
WATCHDOG_PID=$!
kill -TERM $WATCHDOG_PID
If the ALRM signal is sent while openssl
is running nothing happens. Even if the openssl
is in the background the trap is never called
timeout(1)
?