I’m trying to use the signaling mechanism of UNIX to do some processing. To test out this functionality, I wrote the following code:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
void handler(int sig)
{
printf("Received %d signal in %d!n", sig, getpid());
if(sig == SIGUSR2)
exit(0);
signal(sig, handler);
}
int main()
{
pid_t child = fork();
if(child == 0)
{
// Child process
while(1)
{
signal(SIGUSR1, handler);
signal(SIGUSR2, handler);
pause();
}
}
else
{
// Parent Process
for(int i = 0; i < 10; i++)
{
printf("Sending SIGUSR1 signal to %dn", child);
kill(child, SIGUSR1);
sleep(1);
}
printf("Sending SIGTERM signaln");
kill(child, SIGTERM);
wait(NULL);
}
}
I am compiling this code using gcc main.c -o test
. When I run this code on my ArchLinux laptop, I get the following output:
Sending SIGUSR1 signal to 212965
Sending SIGUSR1 signal to 212965
Sending SIGUSR1 signal to 212965
Sending SIGUSR1 signal to 212965
Sending SIGUSR1 signal to 212965
Sending SIGUSR1 signal to 212965
Sending SIGUSR1 signal to 212965
Sending SIGUSR1 signal to 212965
Sending SIGUSR1 signal to 212965
Sending SIGUSR1 signal to 212965
Sending SIGTERM signal
As you can see the child process does not print any messages when I run this code on my machine. However, when I run the exact same code on a Ubuntu VM, I get this output:
Sending SIGUSR1 signal to 1153
Received 10 signal in 1153!
Sending SIGUSR1 signal to 1153
Received 10 signal in 1153!
Sending SIGUSR1 signal to 1153
Received 10 signal in 1153!
Sending SIGUSR1 signal to 1153
Received 10 signal in 1153!
Sending SIGUSR1 signal to 1153
Received 10 signal in 1153!
Sending SIGUSR1 signal to 1153
Received 10 signal in 1153!
Sending SIGUSR1 signal to 1153
Received 10 signal in 1153!
Sending SIGUSR1 signal to 1153
Received 10 signal in 1153!
Sending SIGUSR1 signal to 1153
Received 10 signal in 1153!
Sending SIGUSR1 signal to 1153
Received 10 signal in 1153!
Sending SIGTERM signal
My machine is running Linux Kernel v6.11.3
and the VM is running Linux Kernel v6.8.0
. Since the signals API is a part of the UNIX standard, the kernel version should not matter. Then why is it that I can’t see any messages from the child process when I run the code on my machine?
To figure out what the issue on my machine is, I re-ran the code multiple times after commenting out various lines one by one. The problem seems to be with the kill
syscall. If I comment out the calls to kill
, the child process starts printing messages. However, if my code contains calls to kill
, the the child process does not print out anything. Why is this happening? What am I doing wrong?
2
Answers
I found the issue. The problem was that the parent was sending the signals to the child before the child could register the signal handler in the first place. Since the default behavior when
SIGUSR1
andSIGUSR2
is received is to terminate, the child was exiting before it could print anything. Adding a 1 second delay in the parent process fixed the issue.This may or may not solve your issue, It is recommended to use
sigaction()
instead ofsignal()
. sigaction() is more consistent and reliable, allowing better control over signal delivery and handling. Generally, from experience, sigaction is a lot more portable, as concured by the GNU Docs.