Could anybody please tell me the reason to why pending signals are not inherited by the child process?
Os sinais vêm em dois tipos, síncrono e assíncrono. Os síncronos começam com o kernel em resposta a algo que o processo fez - por exemplo, o sempre popular SIGSEGV. Sinais assíncronos geralmente vêm de outros processos e, como o nome indica, chegam a algum ponto arbitrário. Um sinal "pendente" é aquele que ainda não foi entregue ou que foi bloqueado temporariamente pelo processo de recebimento. Considere alguns cenários pendentes e por que seria inadequado para a criança herdá-los.
Síncrono, não entregue: Vamos pegar o exemplo de um SIGSEGV que está pendente porque o pai cometeu uma violação de acesso - algo que, na verdade, não acontece ou não acontece por tempo suficiente para realmente considerá-lo como "pendente" de uma perspectiva de espaço de usuário, mas por causa do argumento - então é o pai que cometeu a violação, não o filho. Se a criança fizer algo semelhante (o que provavelmente aconteceria), ela receberá seu próprio sinal. Se por acaso não, então não deveria receber um que estava pendente para o pai.
Assíncrono, não entregue: Neste caso, realmente não pode ser significativo se o sinal estava pendente pela duração do fork e então entregue ao pai, já que o sinal é assíncrono - não pode ser intencionado interromper o processo em um determinado ponto, é como um telefonema; o interlocutor não está pretendendo pegá-lo enquanto você ainda está sentado em sua cadeira porque o chamador não pode saber disso. O ponto da ligação é apenas comunicar algo para você. Além disso, os sinais são endereçados a um processo específico e o filho é um processo separado com seu próprio PID. Se eu enviar um sinal para processar 1001, não espero que ele também processe 1002.
Bloqueado (síncrono ou assíncrono): Neste caso, o sinal é deixado intencionalmente pelo processo, então ele teve a oportunidade de desbloqueá-lo antes do fork (mas não o fez). Como é sabido que tais sinais não serão herdados pela criança, este cenário ocorre por design . Por exemplo, um servidor recebe um sinal e, por qualquer motivo, decide bloqueá-lo temporariamente enquanto responde a uma solicitação recebida - pselect()
conseguirá isso, eu acho - e para lidar com a solicitação que ele cria um filho. Então ele lida com o sinal pendente.
On the other hand, the child process inherits the signal handlers and signal mask from the parent, why is this done?
Isso parece ser essencial para o conceito de um fork: o filho é uma cópia do pai. Manipuladores de sinal são apenas funções regulares com um propósito especial. Mais uma vez, como isso é conhecido, pode ser explorado por design ou, pelo contrário, compensado. É bastante fácil remover um manipulador se você não quiser mais usá-lo.