tags:

views:

29

answers:

1

I have a function that is responsible for killing a child process when the program ends:

class MySingleton:
    def __init__(self):
        import atexit
        atexit.register(self.stop)

    def stop(self):
        os.kill(self.sel_server_pid, signal.SIGTERM)

However I get an error message when this function is called:

Traceback (most recent call last):
File "/usr/lib/python2.5/atexit.py", line 24, in _run_exitfuncs
   func(*targs, **kargs)
File "/home/commando/Development/Diploma/streaminatr/stream/selenium_tests.py", line 66, in stop
   os.kill(self.sel_server_pid, signal.SIGTERM)
AttributeError: 'NoneType' object has no attribute 'kill'

Looks like the os and signal modules get unloaded before atexit is called. Re-importing them solves the problem, but this behaviour seems weird to me - these modules are imported before I register my handler, so why are they unloaded before my own exit handler runs?

+1  A: 

There are no strong guarantees about the order in which things are destroyed at program termination time, so it's best to ensure atexit-registered functions are self contained. E.g., in your case:

class MySingleton:
    def __init__(self):
        import atexit
        atexit.register(self.stop)
        self._dokill = os.kill
        self._thesig = signal.SIGTERM

    def stop(self):
        self._dokill(self.sel_server_pid, self._thesig)

This is preferable to re-importing modules (which could conceivably cause slowdown of program termination and even unending loops, though that risk is lesser for "system-supplied" modules such as os).

Alex Martelli