Reputation: 169
I am learning inter-process communication in Linux, using kill() to send signals to sleeping child process.Here is my program:
8 void func(void);
9 int main(void){
10 int i, j;
11 pid_t status, retpid;
12 signal(17,func);
13 if( i = fork() ){
14 printf("Parent:signal 17 will be sent to child!\n");
15 kill(i, 17);
16 wait(0);
17 printf("child process terminated\n");
18 }
19 else{
20 sleep(10);
21 printf("Child: A signal from my parent is received!\n");
22 exit(0);
23 }
24 }
25 void func(void)
26 {
27 printf("the signal has been sent!\n");
28 }
Compiled with gcc,the program produced abnormal result,in which func() executed twice:
./test4.out
Parent:signal 17 will be sent to child!
the signal has been sent!
Child: A signal from my parent is received!
the signal has been sent!
child process terminated
I analyzed the result and then deleted the following two line:
16 wait(0);
17 printf("child process terminated\n");
And the result became normal,with func() called only once. It seems that the culprit is wait() function,but why would it ever call a signal handler?
Upvotes: 1
Views: 1936
Reputation: 16540
after correcting (most) of the errors in the posted code..
The result is the following code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
void func( int );
int main(void)
{
pid_t i;
//pid_t status;
//pid_t retpid;
signal(17,func);
if( (i = fork()) )
{
printf( "the fork'd child pid:%d\n", i );
printf("Parent:signal 17 will be sent to child!\n");
kill(i, 17);
wait(NULL);
printf("child process terminated\n");
}
else
{
sleep(10);
printf("Child: pid:%d\n", getpid());
exit(0);
}
}
void func( int theSignal)
{
if( 17 == theSignal )
{
fprintf( stdout, "the 17 signal has been processed by %d!\n", getpid());
}
else
{
fprintf( stdout, "the %d signal is processed\n", theSignal );
}
}
and the output is:
the fork'd child pid:4845
Parent:signal 17 will be sent to child!
the 17 signal has been processed by 4845!
Child: pid:4845
the 17 signal has been processed by 4844!
child process terminated
Which clearly shows that both the parent and the child process the signal
EDIT:
However when a unique SIGUSR2 value is used as in the following code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
void func( int );
#define MY_SIGNAL (31)
int main(void)
{
pid_t i;
//pid_t status;
//pid_t retpid;
signal(17,func);
signal(31,func);
if( (i = fork()) )
{
printf( "the fork'd child pid:%d\n", i );
printf("Parent:signal %d will be sent to child!\n", MY_SIGNAL);
kill(i, MY_SIGNAL);
wait(NULL);
printf("child process terminated\n");
}
else
{
sleep(10);
printf("Child: pid:%d\n", getpid());
exit(0);
}
}
void func( int theSignal)
{
if( MY_SIGNAL == theSignal )
{
printf("the %d signal has been processed by %d!\n", MY_SIGNAL, getpid());
}
else
{
printf( "the %d signal is processed\n", theSignal );
}
}
then the output is:
the fork'd child pid:5099
Parent:signal 31 will be sent to child!
the 31 signal has been processed by 5099!
Child: pid:5099
the 17 signal is processed
child process terminated
which clearly shows the child processed signal 31 (SIGUSR2) and the parent processed signal 17 (SIGCHLD)
Upvotes: 0
Reputation: 361730
You're sending signal 17 to the child process, so its handler is invoked as expected.
Signal 17 is SIGCHLD
. SIGCHLD
is sent to a parent process when a child process dies. The parent's handler is being called when the child exits. This signal isn't coming from the parent; it's coming from the OS, to notify the parent of the child's death.
Upvotes: 2