esse comportamento tem me deixado louco ultimamente, embora provavelmente haja uma explicação razoável, talvez até uma solução.
Atualmente estou aprendendo C e tenho que escrever meu próprio shell na escola e estava explorando o sinal SIGQUIT. Achei algo estranho: quando escrevo um programa C "normal" e dou SIGQUIT usando Ctrl- \, ele faz SIGQUIT e envia uma mensagem dizendo "Quit (core dumped)". É o mesmo que, por exemplo, digitar "cat" no bash e depois Ctrl- \.
No entanto, quando coloco exatamente o mesmo programa em um processo filho usando fork, dizendo ao pai para SIG_IGN e ao filho para SIG_DFL, o filho receberá o sinal SIGQUIT e o processo será encerrado, mas a mensagem de erro mencionada acima não será exibida. Também usei waitpid para capturar o status e analisá-lo com WTERMSIG e ele diz que é 3, então foi encerrado por SIGQUIT. Anexei um código de exemplo para demonstrar meu problema, pois o código do shell que escrevi até agora é enorme.
Exemplo demonstrando o problema
int main(int argc, char **argv, char **envp)
{
signal(SIGQUIT, SIG_IGN);
int pid = fork();
// signal(SIGQUIT, SIG_IGN);
if (pid == 0)
{
signal(SIGQUIT, SIG_DFL);
// execve("/usr/bin/cat", argv, envp);
char buffer[100];
read(0, buffer, 50);
printf("buffer: %s\n", buffer);
return (0);
}
int status;
waitpid(pid, &status, 0);
printf("Status: %i\n", WIFSIGNALED(status));
if (WIFSIGNALED(status))
printf("Signal: %i\n", WTERMSIG(status));
#ifdef WCOREDUMP
if (WCOREDUMP(status))
printf("Core dumped!\n");
#endif
return (0);
}
Outras coisas que tentei
- ulimit -c ilimitado
- configurando SIGQUIT para SIG_IGN antes e depois da bifurcação (veja o código de exemplo)
- tentei com execve e "cat" - mesmo comportamento
- Executar o programa sem fork() se comporta conforme o esperado.
- core_uses_pid está definido como 1
- core_pipe_limit está definido como 0
- core_pattern diz: |/wsl-capture-crash %t %E %p %s
- Eu uso o wsl2 com o Ubuntu, mas já testei o programa em um computador da escola executando o Ubuntu "normal" e obtive o mesmo comportamento
Talvez esse comportamento também seja esperado? Mas se for, por quê? A razão pela qual isso é um problema para mim é que meu shell deve lidar com sinais semelhantes ao bash, então, no final, eu gostaria que a interrupção do cat se comportasse como interromper o cat no bash, se possÃvel. Se não for, eu realmente quero saber por que há um comportamento diferente dos processos pai e filho.
Muito obrigado a todos antecipadamente! É minha primeira pergunta aqui, então, por favor, me avisem também, se eu puder melhorar minha pergunta no futuro.
Certo. Se seu programa (chame-o de
a.out
) deve funcionar como um shell tÃpico, ele precisará notar o término anormal de seus filhos e imprimir uma mensagem, como o bash faz.A mensagem que você à s vezes vê é produzida pelo seu shell bash notando que um filho imediato foi encerrado de forma anormal, neste caso, por SIGQUIT. Quando você introduz o fork e ignora SIGQUIT, o filho do seu shell bash não é encerrado. Assim, o bash não percebe nada e não imprime nada:
Há mais nuances no comportamento do shell do que isso, especialmente pipelines e grupos de processos em primeiro plano, mas o acima é seu problema básico.
Observe que se WIFSIGNALED && WCOREDUMP forem verdadeiros, então um dump de núcleo foi gerado e foi para algum lugar. (Você não apresenta evidências de que procurou e encontrou arquivos de núcleo.)