Além do problema de "muitos sinais", os sinais podem ser explicitamente ignorados. De man 2 signal
:
If the signal signum is delivered to the process, then one of the
following happens:
* If the disposition is set to SIG_IGN, then the signal is ignored.
Os sinais também podem ser bloqueados. De man 7 signal
;
A signal may be blocked, which means that it will not be delivered
until it is later unblocked. Between the time when it is generated
and when it is delivered a signal is said to be pending.
Conjuntos de sinais bloqueados e ignorados são herdados por processos filhos, portanto, o processo pai do aplicativo ignorou ou bloqueou um desses sinais.
O que acontece quando vários sinais são entregues antes que o processo termine de lidar com os anteriores? Isso depende do sistema operacional. A página de signal(2)
manual vinculada acima discute:
- O sistema V redefiniria a disposição do sinal para o padrão. Pior, a entrega rápida de vários sinais resultaria em chamadas recursivas (?).
- O BSD bloqueará automaticamente o sinal até que o manipulador esteja pronto.
- No Linux, isso depende dos sinalizadores de compilação definidos para o GNU
libc
, mas eu esperaria o comportamento do BSD.
signal(2)
sugere enfaticamente que você evite essa confusão usandosigaction(2)
.Você não pode confiar que todos os sinais enviados serão entregues. Por exemplo, o kernel do linux "coalesce" o SIGCHLD se um processo demorar muito no tratamento do SIGCHLD a partir de um processo filho encerrado.
Para responder a outra parte da sua pergunta, os sinais são "enfileirados" dentro do kernel se um número de sinais diferentes chegar em um intervalo muito curto.
Você deve usar
sigaction()
para configurar o manipulador de sinal com osa_sigaction
membro desiginfo_t
, configurando osa_mask
membro dosiginfo_t
argumento com cuidado. Eu acho que isso significa mascarar todos os sinais "assíncronos", pelo menos. De acordo com a página de manual do Linuxsigaction()
, você também irá mascarar o sinal que está sendo tratado. Acho que você deve definir osa_flags
membro como SA_SIGINFO, mas não me lembro por que tenho essa superstição. Acredito que isso fará com que seu processo seja um manipulador de sinal que permaneça definido sem condições de corrida e que não seja interrompido pela maioria dos outros sinais.Escreva sua função de tratamento de sinal com muito, muito cuidado. Basicamente, apenas defina uma variável global para indicar que um sinal foi capturado e o restante do processo lide com a ação desejada para esse sinal. Os sinais serão mascarados pelo menor tempo possível.
Além disso, você desejará testar seu código de manipulação de sinais com muito cuidado. Coloque-o em um pequeno processo de teste e envie o maior número possível de sinais SIGUSR1 e SIGUSR2, talvez de 2 ou 3 programas de envio de sinal para fins especiais. Misture alguns outros sinais também, depois de ter certeza de que seu código pode lidar com SIGUSR1 e SIGUSR2 de maneira rápida e correta. Prepare-se para depuração difícil.
Se você estiver usando linux e somente linux, pode pensar em usar
signalfd()
para criar um descritor de arquivo que possa serselect()
pesquisado para receber esses sinais. O usosignalfd()
pode facilitar a depuração.fonte
É garantido que um sinal seja entregue, no sentido de que se um processo chamar com êxito
kill
, o alvo receberá o sinal. Isso é assíncrono: o remetente não tem como saber quando o sinal é recebido ou processado. No entanto, isso não garante que o sinal seja entregue. O alvo pode morrer antes de poder processar o sinal. Se o alvo estiver ignorando o sinal no momento em que é entregue, o sinal não terá efeito. Se o alvo receber várias instâncias do mesmo número de sinal antes de processá-las, os sinais podem (e geralmente são) mesclados: se você enviar o mesmo sinal duas vezes para um processo, não poderá saber se o processo receberá o sinal. uma vez ou duas vezes. Os sinais são projetados principalmente para matar um processo ou, como forma de fazer com que um processo preste atenção, eles não são projetados para comunicação como tal.Se você precisar de entrega confiável, precisará de um mecanismo de comunicação diferente. Existem dois mecanismos principais de comunicação entre processos: um tubo permite a comunicação unidirecional; um soquete permite comunicação bidirecional e várias conexões com o mesmo servidor. Se você precisar que o destino processe quantas notificações forem enviadas, envie bytes por um canal.
fonte
O kernel é livre para unir sinais padrão se mais de um for entregue enquanto bloqueado. Sinais em tempo real, por outro lado, não são igualmente prejudicados.
Na página de manual do sinal (7) :
Tente usar um sinal com um número no intervalo SIGRTMIN a SIGRTMAX.
fonte
ulimit -i
mostra esse valor como 63432 no Ubuntu 18.04.