O sinal pode ser ignorado (perdido)?

8

Eu tenho uma aplicação que está se comunicando com os trabalhadores via sinais (particulary SIGUSR1 / SIGUSR2 / SIGSTOP).

Posso confiar que, aconteça o que acontecer, todos os sinais serão entregues e processados pelo handler?

O que acontece se os sinais forem enviados mais rapidamente do que não é possível para o aplicativo manipulá-los (por exemplo, devido à alta carga de host no momento)?

    
por KaP 27.01.2015 / 22:06

4 respostas

7

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.

Os conjuntos de sinais bloqueados e ignorados são herdados por processos filhos, portanto, pode acontecer que o processo pai de sua aplicação tenha ignorado ou bloqueado um desses sinais.

O que acontece quando vários sinais são entregues antes de o processo terminar de lidar com os anteriores? Isso depende do sistema operacional. A% man_de% manpage vinculada acima discute:

  • O System V redefiniria a disposição do sinal para o padrão. Pior, a rápida entrega de múltiplos sinais resultaria em chamadas recursivas (?).
  • O BSD bloquearia automaticamente o sinal até que o manipulador seja concluído.
  • No Linux, isso depende dos sinalizadores de compilação definidos para o GNU signal(2) , mas esperaria o comportamento do BSD.
por 27.01.2015 / 22:35
6

Você não pode confiar que todos os sinais enviados serão entregues. Por exemplo, o kernel do linux "une-se" ao SIGCHLD se um processo demorar muito para lidar com SIGCHLD de uma criança que saiu processo.

Para responder a outra parte da sua pergunta, os sinais ficam "enfileirados" dentro do kernel se um número de sinais diferentes chegarem em um intervalo muito curto.

Você deve usar sigaction() para configurar o manipulador de sinal com o sa_sigaction membro de siginfo_t , definindo cuidadosamente o sa_mask membro do argumento siginfo_t . Eu acho que isso significa mascarar todos os sinais "assíncronos", pelo menos. De acordo com a página man do Linux sigaction() , você também irá mascarar o sinal sendo manipulado. Eu acho que você deve definir o membro sa_flags para 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 sinais 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 manipulador de sinal com muito cuidado. Basicamente, basta definir uma variável global para indicar que um sinal foi capturado e fazer com que 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ê vai querer testar seu código de tratamento de sinal muito bem. 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 sinais para fins especiais. Misture alguns outros sinais também, depois que você estiver confiante de que seu código pode manipular SIGUSR1 e SIGUSR2 rapidamente e corretamente. Prepare-se para uma depuração difícil.

Se você estiver usando linux e somente linux, você pode pensar em usar signalfd() para criar um descritor de arquivo que você pode select() ou poll para receber esses sinais. Usar signalfd() pode facilitar a depuração.

    
por 27.01.2015 / 22:34
5

Um sinal é garantido para ser entregue, no sentido de que, se um processo chamar com sucesso 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 será entregue. O alvo pode morrer antes de processar o sinal. Se o alvo está 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 poder 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 ou duas vezes. Sinais são principalmente projetados para matar um processo ou como uma maneira de fazer um processo prestar atenção, eles não são projetados para comunicação como tal.

Se você precisar de uma entrega confiável, precisará de um mecanismo de comunicação diferente. Existem dois mecanismos de comunicação principais entre os processos: um tubo permite a comunicação unidirecional; um socket permite comunicação bidirecional e várias conexões para o mesmo servidor. Se você precisar que o alvo processe tantas notificações quantas forem enviadas, envie bytes através de um pipe.

    
por 28.01.2015 / 01:47
0

O kernel está livre para coalescer sinais padrão se mais de um for entregue enquanto bloqueado. Sinais em tempo real, por outro lado, não são similarmente deficientes.

Na página de manual do (7) :

Real-time signals are distinguished by the following:

  1. Multiple instances of real-time signals can be queued. By contrast, if multiple instances of a standard signal are delivered while that signal is currently blocked, then only one instance is queued.

Tente usar um sinal com um número no intervalo SIGRTMIN para SIGRTMAX.

    
por 20.04.2016 / 17:29

Tags