Problema resolvido, apesar de ser um erro de programação e não relacionado ao Upstart. O programa abre o dispositivo ttyUSB para entrada bruta (não-canônica), mas não estava limpando o sinalizador ISIG em termios. Sempre que um caractere "CTRL-C" (0x02) foi recebido, o kernel gerou o SIGINT e o enviou para o programa. Esse problema não estava acontecendo no bash porque as configurações do termios são persistentes em um arquivo, e algo deve ter aberto o tty e limpado o bit ISIG antes que meu programa fosse executado. Isso não ocorreu ao executá-lo diretamente do Upstart. Eu ainda gostaria que houvesse uma maneira melhor de registrar / depurar sinais, o ptrace é apenas metade da resposta!