this behaviour has been driving me crazy, lately, though there is probably a reasonable explanation, maybe even a fix.
I am currently learning C and have to write my own shell in school and was exploring the SIGQUIT signal. I found something odd: When I write a "normal" C program and give it SIGQUIT by using Ctrl-\, it will SIGQUIT and send a message saying "Quit (core dumped)". It is the same as for example typing "cat" in bash and then Ctrl-\.
However, when I put the exact same program in a child process by using fork, telling the parent to SIG_IGN and the child to SIG_DFL, the child will receive the SIGQUIT signal and the process is terminated but the above-mentioned error message does not show. I also used waitpid to catch the status and analyze it with WTERMSIG and it says, it is 3, so it was terminated by SIGQUIT. I have attached an example code to demonstrate my problem since the shell code I have written so far is huge.
Example demonstrating the issue
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);
}
Other things I have tried
Maybe this behaviour is also to be expected? But if so - why? The reason why this is even a problem for me is that my shell should handle signals similar to bash, so in the end I would like the interruption of cat to behave like interrupting cat in bash, if at all possible. If it is not, I really want to know why there is different behaviour from parent and child processes.
Thank you all very much in advance! It is my first question on here, so please kindly let me also know, if I can improve my question in the future.
my shell should handle signals similar to bash, so in the end I would like the interruption of cat to behave like interrupting cat in bash
Right. If your program (call it a.out
) is to function like a typical shell, it will need to notice the abnormal termination of its children and print a message, like bash does.
The message you sometimes see is produced by your bash shell noticing that an immediate child terminated abnormally, in this case, by SIGQUIT. When you introduce the fork and ignore SIGQUIT, your bash shell's child does not terminate. Thus bash notices nothing, and prints nothing:
bash | bash
\ | \
cat (SIGQUIT:SIG_DFL) | a.out (SIGQUIT:SIG_IGN)
| \
| cat (SIGQUIT:SIG_DFL)
------------------------+--------------------------
Here bash notices cat's | Here bash is unaware of
abnormal termination | any grandchildren at all
There are more nuances to shell behavior than this, especially pipelines and foreground process groups, but the above is your basic problem.
Note that if WIFSIGNALED && WCOREDUMP are true, then a core dump was generated and went somewhere. (You do not present evidence that you looked for and found core files.)