clinuxlinux-kernel

SIGTERM to child process kills parent too


when I do

pid_t pid = fork();
...
if (pid == 0) 
     execvp(...);
...
if (pid > 0) {
     kill(pid, SIGTERM); 
}

it kills the child , that's okay , but it kills parent process too (not sure that is important but parent process has custom sig handlers) .

is it right behavior ? or I do something wrong? how to prevent a killing of parent process?

expected logic is to stop the child if parent doesn't receive some notifications during predefined time range. then run new child instance again


Solution

  • It works fine for me:

    int main(void) 
    {
        pid_t child_pid = fork();  
    
        if (child_pid == -1) 
        {
            perror("fork failed");
            exit(1);
        }
        else if (child_pid == 0) 
        {
            // In the child process
            printf("Child process started with PID %d\n", getpid());
            while (1) 
            {
                printf("Child is running...\n");
                fflush(stdout);
                usleep(1000);
            }
        }
        else 
        {
            // In the parent process
            printf("Parent process with PID %d created child with PID %d\n", getpid(), child_pid);
            fflush(stdout);
            // Give the child some time to run
            usleep(35000);
    
            // Terminate the child process
            printf("Parent is killing the child process...\n");
            kill(child_pid, SIGTERM);  
    
            waitpid(child_pid, NULL, 0);
    
            printf("Child process terminated. Parent continues...\n");
            // The parent process continues running
        }
    
        return 0;
    }
    

    https://godbolt.org/z/G7YzqsvYn

    Try also this for testing. It does not work on Godbolt - most likely it does not allow the execution of other programs.

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>
    #include <sys/wait.h>
    
    int main(void)
    {
        pid_t child_pid = fork();
    
        if (child_pid == -1)
        {
            perror("fork failed");
            exit(1);
        }
        else if (child_pid == 0)
        {
            printf("Child process (PID %d) locating 'sleep' command...\n", getpid());
    
            int pipefd[2];
            if (pipe(pipefd) == -1)
            {
                perror("pipe failed");
                exit(1);
            }
    
            pid_t which_pid = fork();
            if (which_pid == -1)
            {
                perror("fork failed");
                exit(1);
            }
    
            if (which_pid == 0)
            {
                close(pipefd[0]);
                dup2(pipefd[1], STDOUT_FILENO);
                execlp("which", "which", "sleep", (char *)NULL);
                perror("whick execlp failed");
                exit(1);
            }
            else
            {
                close(pipefd[1]);
                waitpid(which_pid, NULL, 0);
    
                char sleep_path[256];
                ssize_t bytes_read = read(pipefd[0], sleep_path, sizeof(sleep_path) - 1);
                if (bytes_read > 0)
                {
                    sleep_path[bytes_read] = '\0';
                    printf("Location of 'sleep': %s", sleep_path);
                }
                else
                {
                    perror("failed to read from pipe");
                }
                close(pipefd[0]);
                sleep_path[strcspn(sleep_path, "\n")] = '\0';  // Trim newline
                char *args[] = { sleep_path, "10", NULL };
                printf("Path: %s\n", args[0]);
                execvp(args[0], args);
    
                perror("execvp failed");
                exit(1);
            }
        }
        else
        {
            printf("Parent process (PID %d) created child (PID %d)\n", getpid(), child_pid);
    
            sleep(3);
    
            printf("Parent is sending SIGTERM to child...\n");
            kill(child_pid, SIGTERM);
    
            waitpid(child_pid, NULL, 0);
    
            printf("Child process terminated. Parent continues...\n");
        }
    
        return 0;
    }
    

    I can confirm - it works (I just added printing paths to found sleep):

    Parent process (PID 6017) created child (PID 6028)
    Child process (PID 6028) locating 'sleep' command...
    Location of 'sleep': /usr/bin/sleep
    Path: /usr/bin/sleep
    Parent is sending SIGTERM to child...
    Child process terminated. Parent continues...