7

Anyone has any idea how to get my destructor called on object destruction?

def __del__(self):
    os.unlink(self.pidfile)

Scenario: There is a Daemon that runs Process. Daemon gets a SIGTERM, and immediately sends a SIGTERM to Process. Process stops execution without __del__ called.

Rápli András
  • 3,869
  • 1
  • 35
  • 55
  • Are there still references to that stopped process? – Patrick Haugh Nov 15 '16 at 17:59
  • 5
    You can't. Finalizers are not guaranteed to run. Use [the `with` statement](https://docs.python.org/3/reference/compound_stmts.html#the-with-statement) instead of `__del__()`. Then set a signal handler for `SIGTERM` that raises an exception which the `with` statement can react to. – Kevin Nov 15 '16 at 18:02
  • 2
    @Kevin: Finalizers aren't guaranteed to run, but we actually have more problems than that, because context manager `__exit__`s and `finally` blocks don't run by default either when Python gets a SIGTERM. – user2357112 Nov 15 '16 at 18:04

1 Answers1

5

As referenced in the comments, defining an __exit__ method for your object and using the with statement is the preferred way of "destructing" objects. It's more explicit and predictable.

However, even using the with statement won't guarantee clean destruction of your object if a SIGTERM is received. In order to do something when a signal is received, you'll have to add a signal handler.

import signal
import sys

def handle_signal(signum, frame):
    print('Got signal')
    #  Do some cleanup
    sys.exit(signum)  # Maybe ???

signal.signal(signal.SIGTERM, handle_signal)

At this point, you might consider calling del your_object in the signal handler, but even that is not guaranteed to call the __del__ method if there are still references to that object in the program (see the docs for __del__)

So bottom line I think is not to expect things to go absolutely smoothly and predictably if you're depending on SIGTERM to close your Python programs.

Billy
  • 5,179
  • 2
  • 27
  • 53