47

What does Python do under the covers by default if it receives a SIGTERM but there is no signal handler registered for it?

meteoritepanama
  • 6,092
  • 14
  • 42
  • 55

3 Answers3

36

Building on the answer of Thomas Wouters, python does not register a handler for the SIGTERM signal. We can see this by doing:

In[23]: signal.SIG_DFL == signal.signal(signal.SIGTERM,signal.SIG_DFL)
Out[23]: True

That means that the system will take the default action. On linux, the default action (according to the signal man page) for a SIGTERM is to terminate the process.

Terminating a process means that:

  • the process will simply not be allocated any more time slices during which it can execute code.

    • This means that it will not raise an exception, or call the code in try: finally: blocks, or the __exit__ method of context managers. It will not do those things because that particular python interpreter will never get the chance to execute another instruction.
  • The process's memory and other resources (open files, network sockets, etc...) will be released back to the rest of the system.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
stochastic
  • 3,155
  • 5
  • 27
  • 42
  • 6
    This is so true, important and - at least to me - unintuitive. I thought the whole business of finally clauses and \__exit__ methods of context-managers was to make sure the code in question is always run (except a SIGKILL, which I was aware of is handled on a system level). Struggled several days with this and only now came to the realization that you already presented here in your answer. I need to keep this in mind. – matlehmann Mar 24 '17 at 11:12
25

Nothing. Python itself does not register a signal handler for it. You can check this in the interactive interpreter:

>>> import signal
>>> signal.signal(signal.SIGTERM, signal.SIG_DFL)
0
>>> signal.SIG_DFL
0

That shows signal.signal() returning signal.SIG_DFL for signal.SIGTERM. Contrast it with signal.SIGINT, which does have a default signal handler (which raises KeyboardInterrupt):

>>> signal.signal(signal.SIGINT, signal.SIG_DFL)
<built-in function default_int_handler>
Thomas Wouters
  • 130,178
  • 23
  • 148
  • 122
  • 7
    This also means that functions registered via `atexit.register()` won't be called if the process is terminated by `SIGTERM`. – Sven Marnach Mar 29 '12 at 18:16
  • 18
    Ok fine, but what does it DO? Exit uncleanly? Ignore it completely? Something else? – Lucretiel May 06 '16 at 21:09
  • Immediately dies. Python just completely ignores the signal, and therefore dies immediately. Python does not "do" anything. That's my own reading/understanding of what people are saying above. Someone can feel free to chime in and correct me if I've misunderstood. – Hugh Perkins Jan 01 '23 at 20:27
  • (presumably however, we could register our own handler that does raise a normal exception?) – Hugh Perkins Jan 01 '23 at 20:27
1

Look at this example:

import time

class A:
    def __init__(self):
        print("A.__init__()")

    def __del__(self):
        print("A.__del__()")

a = A()
b = A()

time.sleep(10)

Under normal circumstances, the output would be:

A.__init__()
A.__init__()
A.__del__()
A.__del__()

But if you kill it with SIGTERM you get:

A.__init__()
A.__init__()
Terminated

Thus the program does not terminate cleanly (the destructors are not called).

user803422
  • 2,636
  • 2
  • 18
  • 36
  • Yes, that is the default action when a process doesn't register a SIGTERM handler. And that's what Thomas Wouters' answer tells us already, and stochastic makes explicit. – Martijn Pieters Oct 08 '19 at 16:53