waitpid stops waiting after signal is sent

Viewed 144

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.

1 Answers

Per POSIX waitpid() documentation:

RETURN VALUE

... If wait() or waitpid() returns due to the delivery of a signal to the calling process, -1 shall be returned and errno 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 );
Related