Para responder a essa pergunta, você precisa entender como os sinais são enviados para um processo e como um processo existe no kernel.
Cada processo é representado como task_struct
dentro do kernel (a definição está no arquivo de cabeçalho sched.h
e beginns aqui . Essa estrutura contém informações sobre o processo; por exemplo o pid. As informações importantes estão na linha 1566 onde o sinal associado é armazenado. Isso é definido apenas se um sinal for enviado ao processo.
Um processo morto ou um processo zumbi ainda tem task_struct
. A estrutura permanece, até que o processo pai (natural ou por adoção) tenha chamado wait()
depois de receber SIGCHLD
para colher seu processo filho. Quando um sinal é enviado, o signal_struct
é definido. Não importa se o sinal é acessível ou não, neste caso.
Os sinais são avaliados sempre que o processo é executado. Ou, para ser exato, antes o processo seria executado. O processo está, então, no estado TASK_RUNNING
. O kernel executa a rotina schedule()
, que determina o próximo processo em execução de acordo com seu algoritmo de agendamento. Assumindo que este processo é o próximo processo em execução. Então o valor do signal_struct
é avaliado, se existe um sinal de espera a ser tratado ou não. Se um manipulador de sinal é definido manualmente (via signal()
ou sigaction()
), a função registrada é executada, se não o signal é executada. A ação padrão depende do sinal que está sendo enviado.
Por exemplo, o manipulador padrão do sinal SIGSTOP
alterará o estado do processo atual para TASK_STOPPED
e, em seguida, executará schedule()
para selecionar um novo processo a ser executado. Observe que SIGSTOP
não pode ser acessado (como SIGKILL
), portanto, não há possibilidade de registrar um manipulador de sinal manual. No caso de um sinal não detectável, a ação padrão será sempre executada.
Para sua pergunta:
Um processo extinto ou morto nunca será determinado pelo agendador para estar novamente no estado TASK_RUNNING
. Assim, o kernel nunca executará o manipulador de sinais (padrão ou definido) para o sinal correspondente, qualquer que seja o sinal. Portanto, o exit_signal
nunca será definido novamente. O sinal é "delievered" para o processo, definindo o signal_struct
em task_struct
do processo, mas nada mais acontecerá, porque o processo nunca será executado novamente. Não há código para rodar, tudo o que resta do processo é aquele struct do processo.
Se o processo pai, no entanto, colhe seus filhos por wait()
, o código de saída que recebe, é aquele em que o processo "inicialmente" morreu. Não importa se há um sinal aguardando para ser tratado.