I am currently working on a C project for university. Among other things I should signal the parent process using SIGUSR1
.
The problem I'm facing at the moment is that I also need to wait for the child process to terminate so I can safely shut down everything in the end (removing shared Memory etc.).
At the moment I am using sigaction()
to respond to the signal and waitpid()
to wait for the child to terminate (that was the plan anyways ^^). But when I signal the parent using kill()
, waitpid()
stops waiting and runs the remainder of the parent even though the child is still running.
I feel like I'm missing something obvious but I can't figure it out.
Any help is greatly appreciated, stay safe
Tim
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
void handle_sigusr1(int sig) {
printf("Recieved signal %i.\n", sig);
}
int main() {
pid_t pid;
pid = fork();
if (pid == -1) {
perror("fork:");
return EXIT_FAILURE;
}
else if (pid == 0) {
printf("Hello from the child.\n");
kill(getppid(), SIGUSR1);
sleep(3);
printf("Hello again from the child.\n");
return EXIT_SUCCESS;
}
else {
printf("Hello from the parent.\n");
struct sigaction sa;
sa.sa_handler = &handle_sigusr1;
sigaction(SIGUSR1, &sa, NULL);
int status;
waitpid(pid, &status, 0);
if (WIFEXITED(status))
printf("Exit status: %i\n", WEXITSTATUS(status));
printf("Finished waiting for child.\n");
return EXIT_SUCCESS;
}
}
Output:
Hello from the parent.
Hello from the child.
Recieved signal 10.
Exit status: 0
Finished waiting for child.
tim@schlepptop:signalTest$ Hello again from the child.
PS: WEXITSTATUS(status)
is usually 0
but sometimes it's also something like 16
or 128
.
Per POSIX waitpid()
documentation:
RETURN VALUE
... If
wait()
orwaitpid()
returns due to the delivery of a signal to the calling process,-1
shall be returned anderrno
set to[EINTR]
. ...
You need to check the return value:
int status
do
{
errno = 0;
int rc = waitpid(pid, &status, 0);
if ( rc != -1 )
{
break;
}
}
while ( errno == EINTR );