É difícil fazer coisas não triviais em um manipulador de sinal, já que o restante do programa está em um estado desconhecido. A maioria dos manipuladores de sinais apenas definem um flag, que é posteriormente verificado e tratado em outro lugar no programa.
Motivo de não reiniciar a chamada do sistema automaticamente:
Imagine um aplicativo que receba dados de um soquete pelo bloqueio e ininterrupto recv()
chamada do sistema. Em nosso cenário, os dados são muito lentos e o programa fica muito tempo nessa chamada de sistema. Esse programa tem um manipulador de sinal para SIGINT
que define um sinalizador (que é avaliado em outro lugar) e SA_RESTART
é definido para que a chamada do sistema seja reiniciada automaticamente. Imagine que o programa esteja em recv()
, que aguarda dados. Mas nenhum dado chega. Os blocos de chamadas do sistema. O programa agora captura ctrl - c do usuário. A chamada do sistema é interrompida e o manipulador de sinais, que apenas define o sinalizador, é executado. Então, recv()
é reiniciado, ainda esperando por dados. O loop de eventos está preso em recv()
e não tem oportunidade de avaliar o sinalizador e sair do programa normalmente.
Com SA_RESTART
não definido:
No cenário acima, quando SA_RESTART
não está definido, recv()
receberia EINTR
em vez de ser reiniciado. A chamada do sistema sai e, portanto, pode continuar. Claro, o programa deve então (o mais cedo possível) verificar o sinalizador (definido pelo manipulador de sinal) e fazer a limpeza ou o que ele fizer.