Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm writing a script that starts a subshell to go off and do some work. In a special case, the script needs to tell the subshell to cleanly stop what it's doing and exit early. However, my psuedo-code below doesn't seem to be working. Am I trying the impossible? Is it possible to define a separate trap for signals in a subshell?

#!/bin/bash

function myExitFunction { ... }
trap myExitFunction SIGTERM

while [ 1 ] ; do
    waitForSpecialCondition

    kill -0 $SUBSHELL_PID   # check if subshell is running
    if [ $? -eq 0 ] ; then  # and kill it if it is
        kill $SUBSHELL_PID
    fi

    (
    someProcess
    MYOWNCHILD=$!           # save someProcess's pid to kill later if I need to
    trap "kill $MYOWNCHILD" SIGTERM
    ... # do stuff
    ) &
    SUBSHELL_PID=$!

done
share|improve this question
    
General note: signal handling is a little wonky in shells other than ksh. Beware that ( … ) & might create a subprocess of a subprocess; try { … } & instead. Other than that, the principle looks sane. For better answers, post code that we can run and try to fix (i.e. no ... or undefined waitForSpecialCondition). –  Gilles May 24 '11 at 20:06
    
Thanks Gilles. So it is even valid for a sub shell to have it's own signal trap? –  Cory Klein May 24 '11 at 20:10
1  
This question doesn't really make sense. You can change the traps at any point, including when in a subshell. As usual what you do in the subshell doesn't change the state of the parent. Then the difficulty is mainly to bring the signals to the right process. –  Gilles May 24 '11 at 20:13

1 Answer 1

up vote 0 down vote accepted

It turns out that my problem was not what I really thought it was. Below is a script that behaves like the psuedo-code above. It functions exactly as I expected (although a little contrived in order to be simple), and is a good example of having separate signal traps for a parent and child shell process.

This trap functionality can be demonstrated by just running the script, and exiting by a ctrl-c.

#!/bin/bash

function endEarly {
echo "Terminating early"
if [ ! -z $SUBSHELL_PID ] ; then
    echo "Killing subshell with pid $SUBSHELL_PID"
    kill $SUBSHELL_PID
fi
exit
}

trap endEarly SIGTERM SIGINT

echo "Give me some input"
while [ 1 ] ; do
    read INPUT

    # kill the subshell if it exists and is running
    if [ ! -z $SUBSHELL_PID ] ; then
        kill -0 $SUBSHELL_PID
        if [ $? -eq 0 ] ; then
            kill $SUBSHELL_PID
        fi
    fi

    echo "Now I'll repeat your input.  Feel free to change it"
    echo "at any time by typing it again and hitting <Enter>"
    {
        (
            while [ 1 ] ; do
                echo "$INPUT"
                sleep 5
            done
        ) &
        CHILD_PID=$!
        trap "kill $CHILD_PID;" SIGTERM SIGINT
        wait $CHILD_PID
    } &
    SUBSHELL_PID=$!
done
share|improve this answer
3  
Beware that kill -0 $pid tells you if there's a process with this PID, it doesn't tell you whether that's the process you mean. I don't advise this in a production program: sooner or later this will lead to your killing an unrelated critical process that's reused the PID. –  Gilles May 24 '11 at 21:12
    
I hadn't thought of that, but that is a very good observation. Thanks again. –  Cory Klein May 25 '11 at 1:21

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.