0

I want to gracefully release some expensive system resource in my code with event handler. The problem is that the event handler is registered in a forked sub-process (yes, I have to put the event handler there in sub-process, since the resource is allocated after fork) and I want the sub-processes terminate when parent process dies. However, the code does not work as my expectation.

Here is a runnable example:

import time
import os
import signal

PRCTL=None
# get prctl from libc
def getPRCTL():
    global PRCTL
    if PRCTL is None:
        import ctypes
        PRCTL = ctypes.CDLL("libc.so.6")["prctl"]

    return PRCTL

def dieWithParent():
    prctl = getPRCTL()
    prctl(1, signal.SIGTERM)    # 1 = PR_SET_PDEATHSIG

def foo():
    print "In foo."

    def handler(signo, frame):
        print "Handler is activated."

    signal.signal(signal.SIGTERM, handler)

    time.sleep(10)    # in case sub-process terminates first.

if __name__ == '__main__':
    dieWithParent()
    pid = os.fork()
    if 0 == pid:
        foo()
    else:
        print "Subprocess spawned."
        print "dying..."

The code does the following:

  1. instruct OS to turn parent die signal to a SIGTERM;
  2. fork a sub-process;
  3. if child process, register signal handler and wait for parent's termination.

On my platform, the output is

$ python main.py
In foo.
Subprocess spawned.
dying...

It seems the handler is not activated.

Anything wrong with my code or understanding?

Configuration on my box is

2.6.18-238.el5 x86_64 Python 2.6

Any hints will be highly appreciate, thank you!

Summer_More_More_Tea
  • 12,740
  • 12
  • 51
  • 83

2 Answers2

2

from prctl

PR_SET_PDEATHSIG (since Linux 2.1.57) Set the parent process death signal of the calling process to arg2 (either a signal value in the range 1..maxsig, or 0 to clear). This is the signal that the calling process will get when its parent dies. This value is cleared for the child of a fork(2) and (since Linux 2.4.36 / 2.6.23) when executing a set-user-ID or set-group-ID binary.

so you essentially ensure that your parent dies with it's parent, but say nothing about your child process.

if you add:

dieWithParent()

after you fork then it behaves correctly

user3012759
  • 1,977
  • 19
  • 22
-1

If this is an attempt to write a daemon you should look up double forking.

For example: http://code.activestate.com/recipes/66012-fork-a-daemon-process-on-unix/

wojciii
  • 4,253
  • 1
  • 30
  • 39