Acontece que meu problema não era o que eu realmente achava que era. Abaixo está um script que se comporta como o código psuedo acima. Ele funciona exatamente como eu esperava (embora um pouco inventado para ser simples), e é um bom exemplo de ter traps de sinal separados para um processo de shell pai e filho.
Esta funcionalidade de armadilha pode ser demonstrada apenas executando o script e saindo por um 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