O problema é bem explicado aqui , enquanto WCE espera e saída cooperativa e eu encorajo você a lê-lo. Basicamente, seu sinal é recebido por todos os processos em primeiro plano, isto é, o shell e o programa, sleep ou aplay. O programa sai com o código de retorno 130 se não manipular o sinal. A casca faz uma espera para a criança terminar, e vê isso, e o fato de que ela recebeu o sinal também, então sai.
Quando o programa captura o sinal, ele geralmente sai com o código 1 (como acontece com o jogo). Quando o shell aguarda o filho, ele percebe que ele não terminou devido ao sinal e, portanto, tem que assumir que o sinal era um aspecto normal do funcionamento do programa, portanto, o shell continua normalmente.
Para o seu exemplo, a melhor maneira de lidar com o jogo é verificar o código de retorno para não-zero e parar:
(while aplay test.wav; do :; done)
O artigo acima mencionado explica que um programa bem-comportado que queira capturar sigint para fazer alguma limpeza, deve então desabilitar seu manipulador, e voltar a se matar a fim de obter os sinalizadores de saída corretos definidos. / p>