1

It is my objective to make a program with a parent and child process, and when either one them is killed, they are replaced. The part I am struggling with is the case of the parent's death. In this case, the child must step up to become the new parent, and then fork() a child of its own. When I send a SIGKILL to the parent process, my entire program seems to end abruptly, and since I cannot handle a SIGKILL, I am unsure of how to do this properly.

Is there a way to keep the child running in order to become the new parent process?

Thanks

Lance_P
  • 299
  • 2
  • 16
  • When you say "replaced" you mean exchanged or replaced by one another? – PseudoAj May 06 '16 at 04:24
  • The current child (at the time of parent's death) must fork out another child, thus becoming the parent and continuing the parental duties that the previous parent was performing. The new parent can have the same PID as the previous parent, or it can keep the PID it had as a child. Doesn't matter. – Lance_P May 06 '16 at 04:26
  • For clarification, the other case is if only the child were to die. In this case, the parent simply needs to fork a new child. This portion of my program works properly. – Lance_P May 06 '16 at 04:29
  • If possible, would this not be a huge security problem? – Martin James May 06 '16 at 07:54

1 Answers1

2

Normally the child you fork shouldn't be killed when it's parent is killed, unless you do something like: How to make child process die after parent exits?

If the parent is killed, the children become a children of the init process. You probably saw on terminal that the process returns immediately after you send KILL to parent. That's because the sub-bash is waiting only on the parent's PID. But the child is actually running elsewhere.

Here is a example to show it:

#!/usr/bin/env python
# test_parent_child_kill.py
import os
import time

def child():
    print "Child process with PID= %d"%os.getpid()
    time.sleep(20)

def parent():
    print "Parent process with PID= %d"%os.getpid()
    newRef=os.fork()
    if newRef==0:
        child()
    else:
        print "Parent process and our child process has PID= %d"%newRef
        time.sleep(20)

parent()

Then within sleep period:

user@mac:/tmp|⇒  python test_parent_child_kill.py
Parent process with PID= 17430
Parent process and our child process has PID= 17431
Child process with PID= 17431

user@mac:/tmp|⇒  kill 17430

user@mac:/tmp|⇒  ps -ef | grep 17431
503 17431     1   0  9:30PM ttys000    0:00.00 /usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python test_parent_child_kill.py

So the child is actually still alive.

--Edit--

  1. Why when the parent is killed my program exits back to the shell?

Bash invokes the command also via folk/exec via something like this:

childPid = fork();
if (childPid == 0){
    executeCommand(cmd); //calls execvp  
} else {
    if (isBackgroundJob(cmd)){
        record in list of background jobs
    } else {
        waitpid (childPid);
    }       
}

Since from bash's point of view, the parent of your program is the child, it would return to prompt input when it returns from waitpid(childPid).

  1. Is there a way to stay within the program and continue functioning as it was but with a new parent?

It might be a bit difficult if you want to "re-attach", but it's not impossible:

Attach to a processes output for viewing

https://unix.stackexchange.com/questions/58550/how-to-view-the-output-of-a-running-process-in-another-bash-session

Reference:

http://www.cs.cornell.edu/Courses/cs414/2004su/homework/shell/shell.html

slm
  • 15,396
  • 12
  • 109
  • 124
Wei Shen
  • 2,014
  • 19
  • 17