oemer_1907
oemer_1907

Reputation: 31

Child process should not die with parent process

The following scenario:

I have tried fork, exec, screen, p_threads, daemon, and some without success. Every time the doSomeThing.sh starts and kills the process_1.bin, it kills itself because the parent process is killed.

doSomeThing.sh tells me: "leaving program after kill signal!"

Unfortunately, this does not work either:

        pid_t pid;
        pid = fork();
        if (pid < 0)
            exit(EXIT_FAILURE);

        if (pid > 0)            // Success: Let the parent terminate
            exit(EXIT_SUCCESS);

        if (setsid() < 0)
            exit(EXIT_FAILURE);

        pid = fork();
        if (pid < 0)
            exit(EXIT_FAILURE);

        if (pid > 0)
            exit(EXIT_SUCCESS);
    
    //     umask(0);  

    // chdir("/");

        switch(pid)
        {
        case -1: // Fork() has failed
            perror ("fork");
            break;
        case 0: // This is processed by the child
// deamon(0,0);            
          system("/root/doSomeThing.sh");
// system("screen -dmS doSomeThing /root/doSomething.sh")

//     char *name[] = {
//    "/bin/bash",
//    "-c",
//    "/root/doSomeThing.sh",
//    NULL
//    };
//     if(execvp(name[0], name) < 0)
//       perror("execvp");

            exit(0);
            break;
        default:    // This is processed by the parrent
            break;
        }

How can I direct the doSomeThing.sh to kill the process_1.bin but still stay alive itself?

Upvotes: 3

Views: 2567

Answers (2)

Jonathan Leffler
Jonathan Leffler

Reputation: 753475

Your child process should not be dying. Here's a pair of shell scripts simulating what you describe.

process1.bin

#!/bin/sh

echo "$0: at work"
trap 'echo "$0: Death threat received"; exit 1' 1 2 3 13 15

sh doSomething.sh &

echo "$0: so far, so good"
wait
echo "$0: it's sad when all your children die"
ps -f
echo "$0: exiting normally"
exit 0

doSomething.sh

#!/bin/sh
#
# Commit parenticide and continue, preferably without dying.

#PPID=$(ps -fp$$ | colnum -c 3)

echo "Before"
ps -f

(
set -x
kill $PPID
)

sleep 1

echo ""
echo "After"
ps -f

sleep 5
echo "$0: Goodbye, Cruel World!"

One time when I ran it, I got the output:

$ ./process1.bin
./process1.bin: at work
./process1.bin: so far, so good
Before
  UID   PID  PPID   C STIME   TTY           TIME CMD
  501   649   641   0  9:58AM ttys000    0:00.14 -bash
  501 29760   649   0  8:47AM ttys000    0:00.01 sh
  501 29793 29760   0  8:47AM ttys000    0:00.01 /bin/sh ./process1.bin
  501 29794 29793   0  8:47AM ttys000    0:00.01 sh doSomething.sh
  501   661   657   0  9:58AM ttys001    0:00.05 -bash
  501   693   688   0  9:58AM ttys002    0:00.05 -bash
  501   738   731   0  9:58AM ttys007    0:00.31 -bash
  501   769   766   0  9:58AM ttys008    0:00.05 -bash
  501   848   847   0  9:58AM ttys009    0:00.05 -bash
  501   884   881   0  9:58AM ttys010    0:00.12 -bash
  501   946   920   0  9:58AM ttys011    0:00.15 -bash
+ kill 29793
./process1.bin: Death threat received
$ 
After
  UID   PID  PPID   C STIME   TTY           TIME CMD
  501   649   641   0  9:58AM ttys000    0:00.14 -bash
  501 29760   649   0  8:47AM ttys000    0:00.01 sh
  501 29794     1   0  8:47AM ttys000    0:00.01 sh doSomething.sh
  501   661   657   0  9:58AM ttys001    0:00.05 -bash
  501   693   688   0  9:58AM ttys002    0:00.05 -bash
  501   738   731   0  9:58AM ttys007    0:00.31 -bash
  501   769   766   0  9:58AM ttys008    0:00.05 -bash
  501   848   847   0  9:58AM ttys009    0:00.05 -bash
  501   884   881   0  9:58AM ttys010    0:00.12 -bash
  501   946   920   0  9:58AM ttys011    0:00.15 -bash
doSomething.sh: Goodbye, Cruel World!

$

Note that my $ prompt appears after 'Death threat received'. The following output is from doSomething; I hit return after 'Goodbye, Cruel World!' to get the final $ prompt.

Testing with Bash on a MacBook Pro running macOS Catalina 10.15.7.


In a comment, oemer_1907 says:

The shell script kills all processes to play the update (including the C update process). Once the C update process is killed by the shell update process, it sends a SIGTERM to all its children. Hence, the shell script is also killed. If instead it just calculates without killing its parent, then it just keeps running until the end.

Well, if the parent process sends SIGTERM to all its children, your child script, doSomething.sh, must ignore the SIGTERM signal using either of these:

trap "" 15
trap "" TERM

before it sends a signal to its parent. Or the parent process could arrange not to send the signal to this child. Or it could arrange for the child to ignore SIGTERM before it is executed:

signal(SIGTERM, SIG_IGN);
…exec child…

Or …

Upvotes: 1

Serge Ballesta
Serge Ballesta

Reputation: 148870

Apart from ignoring SIGTERM as suggested by Jonathan Leffler, you could make the child process a daemon so that its life will become independant of the life of its parent. Linux has a command to start a process as a daemon daemonize or a library function for a program willing to detach from its parent and its controlling terminal daemon.

Upvotes: 2

Related Questions