Results 1 to 5 of 5
Hi, I have a doubt about signals in C programming. I have done this little program to explain it. It creates a child process with fork and, when the child ...
- 05-23-2011 #1Just Joined!
- Join Date
- May 2010
- Location
- Madrid
- Posts
- 21
little signal question. SIGCHLD for wait(NULL)
Hi, I have a doubt about signals in C programming. I have done this little program to explain it. It creates a child process with fork and, when the child ends, receives the SIGCHLD signal and wait for its termination.
Ok, quite easy, BUT when I execute this code the SIGCHLD signal is received twice, first as an error (returns -1) and the second one to finish the child process.
I don't understand the meaning of the first received signal. Why is it generated? Is the code wrong? any sugestion??
Thanks
(if you add the SIGINT and press Ctrl+C during the execution it also receives two signals instead of one)
Code:#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <signal.h> #include <errno.h> #include <sys/types.h> #include <sys/wait.h> void sighandler(int sign){ pid_t chld_pid; if(sign == SIGCHLD){ fprintf(stderr, "SIGCHLD received\n"); chld_pid = wait(NULL); switch(chld_pid){ case -1: fprintf(stderr, "Unknown error (%d)\n", chld_pid); break; case ECHILD: fprintf(stderr,"ECHILD: The calling process does not have " "any unwaited-for children.\n"); break; case EINTR: fprintf(stderr,"EINTR: WNOHANG was not set and an unblocked " " signal or a SIGCHLD was caught.\n"); break; case EINVAL: fprintf(stderr,"EINVAL: The options argument was invalid.\n"); break; default: fprintf(stderr, "Child %d finished. Closing\n",chld_pid); exit(0); break; } } } int main(int argc, char *argv[]){ pid_t pid; signal(SIGCHLD, sighandler); pid = fork(); if(pid < 0){ fprintf(stderr,"Error in fork\n"); exit(1); }else if(pid == 0){ // son system("uname -a"); sleep(2); exit(0); }else{ // father sleep(100); } }Last edited by occam25; 05-23-2011 at 10:40 AM.
- 05-24-2011 #2Just Joined!
- Join Date
- Jan 2011
- Location
- Fairfax, Virginia, USA
- Posts
- 94
Hi occam25,
I really liked this example ... it turns out the reason for the first -1 return code is from the UNIX system(3) library call. The system() call fork()s a child of its own and runs /bin/sh on your input text. It pauses until the command is complete by doing a wait() embedded inside the system() library call. If you comment out the system() call, you won't get that error. According to "man 3 system":
See what I mean? There are two children, the first from system() which fork()s /bin/sh and the second is your own fork(). The reason there isn't a wait() code for the first child is because its entry in the PID table was released as soon as it was wait()ed ...Code:[...]During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored. [...] This latter return status is in the format specified in wait(2) [...]
By the way, they "say" its a good idea to really limit what you do in a signal handler. For reasons I can't remember now, its bad to do things like printf() ... its best to try to limit the scope of your signal handlers to a flag if you can.Last edited by BrianMicek; 05-24-2011 at 02:36 AM. Reason: Edited for clarification
- 05-24-2011 #3Just Joined!
- Join Date
- Feb 2011
- Posts
- 83
The gcc compiler on my terminal gives the following error of your program:
__________________________________________________ _________________
$ gcc -Wall test-signal.c -o test-signal.bin
test-signal.c: In function ‘main’:
test-signal.c:60: warning: control reaches end of non-void function
__________________________________________________ _________________
It should be seen which is this non-void function.
- 05-24-2011 #4Linux Newbie
- Join Date
- Nov 2008
- Location
- Tokyo, Japan
- Posts
- 243
The reason is because <stdio.h> is a shared library which has its own global variables and state information, and none of these state variables were ever intended to be thread-safe, so using it can lead to race conditions.
Running printf in a signal handler will cause it to execute code, setting various values in global variables in your program's memory. If your program receives a signal while it is executing printf, then the signal handler itself calls printf, the global variables set by the first call to printf will be overwritten by the second call to printf in the signal handler. This can, at best, garble output, and at worst, cause intermittent segment violations and other program failures that are nearly impossible to solve.
When handling signals, it is best to set a flag in a global volatile variable. Once control has been returned to your program's execution loop, and before yielding to another process or reading any more input, your loop should call a routine that checks if the flag has been set, and handles the signal if it has been set.
- 05-24-2011 #5Just Joined!
- Join Date
- May 2010
- Location
- Madrid
- Posts
- 21
Thanks Brian, now it is perfectly clear, I have commented out the system() call and it works as you said. I will have to ckeck which functions are generating signals in my other program.See what I mean? There are two children, the first from system() which fork()s /bin/sh and the second is your own fork(). The reason there isn't a wait() code for the first child is because its entry in the PID table was released as soon as it was wait()ed ...
And good advice about printf().. I did not know it. That kind of details can get you mad searching for an error that you do not see!
yes, I forgot to write the return value for main. Just put a 'return 0;' at the end of main. (main should not be void in order to return a value to the system)The gcc compiler on my terminal gives the following error of your program:
__________________________________________________ _________________
$ gcc -Wall test-signal.c -o test-signal.bin
test-signal.c: In function ‘main’:
test-signal.c:60: warning: control reaches end of non-void function
__________________________________________________ _________________
It should be seen which is this non-void function.
thanks for your help guys


Reply With Quote
