fork () e como os sinais são entregues aos processos

9

Eu programo que escrevi em C fork () em um processo filho. Nenhum dos processos terminará. Se eu iniciar o programa a partir da linha de comando e pressionar control-c, qual processo (es) receberá o sinal de interrupção?

    
por Neil Locketz 28.12.2014 / 08:35

1 resposta

12

Por que não experimentamos e vemos? Aqui está um programa trivial usando signal(3) para interceptar SIGINT no processo pai e filho e imprima uma mensagem identificando o processo quando chegar.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void parent_trap(int sig) {fprintf(stderr, "They got back together!\n");}
void child_trap(int sig) {fprintf(stderr, "Caught signal in CHILD.\n");}
int main(int argc, char **argv) {
    if (!fork()) {
        signal(SIGINT, &child_trap);
        sleep(1000);
        exit(0);
    }
    signal(SIGINT, &parent_trap);
    sleep(1000);
    return 0;
}

Vamos chamar isso de test.c . Agora podemos executá-lo:

$ gcc test.c
$ ./a.out
^CCaught signal in CHILD.
They got back together!

Os sinais de interrupção gerados no terminal são entregues ao grupo de processos ativo, que inclui aqui pai e filho . Você pode ver que child_trap e parent_trap foram executados quando pressionei Ctrl - C .

Há uma longa discussão sobre interações entre fork e sinais no POSIX . A parte mais material disso aqui é que:

A signal sent to the process group after the fork() should be delivered to both parent and child.

Eles também notam que alguns sistemas podem não se comportar exatamente da maneira correta, especialmente quando o sinal chega muito perto do tempo do fork() . Descobrir se você está em um desses sistemas provavelmente vai exigir a leitura do código ou muita sorte, porque as interações são muito improváveis em cada tentativa individual.

Outros pontos úteis são:

  • Um sinal gerado manualmente e enviado para um processo individual (talvez com kill ) será entregue apenas a esse processo, independentemente de ser pai ou filho.
  • A ordem em que os manipuladores de sinais são executados entre os processos não está definida, portanto você não pode confiar na execução em primeiro lugar.
  • Se você não definir um manipulador de interrupções (ou ignorar explicitamente o sinal), ambos os processos simplesmente sairão com um código SIGINT (o comportamento padrão).
  • Se alguém manuseia o sinal não fatalmente e o outro não, aquele sem o manipulador morrerá e o outro continuará.
por 28.12.2014 / 10:01