This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Python unexpectedly ignores a signal after fork
Type: behavior Stage:
Components: Documentation, Interpreter Core Versions: Python 3.6, Python 3.5, Python 2.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: docs@python Nosy List: docs@python, jon orebro, martin.panter, r.david.murray
Priority: normal Keywords:

Created on 2015-11-19 09:00 by jon orebro, last changed 2022-04-11 14:58 by admin.

Files
File name Uploaded Description Edit
example.py jon orebro, 2015-11-19 09:00
example.py martin.panter, 2015-11-20 01:58 Fork bomb removed
Messages (4)
msg254890 - (view) Author: jon orebro (jon orebro) Date: 2015-11-19 09:00
Description:
I found a slight problem with signal handling. It seems that if you have a signal handler setup for a signal, right after a fork the child ignores that signal for a short time. This is regardless of what the signal handler is setup to do. This can cause hangs if the parent immediately kills and then waits for the child. Since the timeframe is small, in practice this only happens sometimes (se example). There might be a reason for this behavour, but in that case I think it should me mentioned in the docs.

What I expected:
I expected the child to, at any point in time, either do the default action for the signal (terminate in this case), or to run the signal handler.

What happens:
It ignores the signal for a short while.

Tested versions:
Python 2.7.6
Python 3.4.0
msg254898 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2015-11-19 14:42
Are you sure this is a python issue and not an OS issue?  That is, does an equivalent C program work correctly?  Since the operation is a fork, I don't think there's anything that python does that would cause the signal to be ignored.

The comment block in the example code here: https://www.win.tue.nl/~aeb/linux/lk/lk-5.html makes me think that the signal getting ignored is a possibility at the OS level, though it isn't explicitly clear.
msg254947 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015-11-20 01:58
Here is a modified version of the script that is not a slow fork bomb. In the original, if time.sleep(600) fails to be interrupted, the children end up continuing the loop and forking more children.

I tried Python 3.5, 2.7 and 3.4. I am seeing the signal completely ignored (at the Python level), not just ignored “for a short while”. Here is a sample output:

$ python3 example.py
Python handler called
Parent waiting for child
Got exit status 0x0000
===
Parent waiting for child
Child: 0
Child: 1
Child: 2
Child: 3
Child: 4
Child: 5
Got exit status 0x0100

David may be right that it is an OS thing, though it does not seem likely IMO. It needs more investigation or expert knowledge.

But I would like to point out that even if the bug of the signal being completely ignored is fixed, the code still has a race condition. The signal could arrive in the window between when Python checks for signals and when it calls sleep(). Then the signal will be ignored until sleep() has returned. If you need this code to be robust, I suggest looking at set_signal_fd() and select().
msg256201 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015-12-11 06:25
I think I figured out the problem. The signal module has a “main_pid” variable which it checks inside the low-level handler: <https://hg.python.org/cpython/file/v3.5.1/Modules/signalmodule.c#l300>. It looks like main_pid gets updated inside PyOS_AfterFork(), but I guess there is a race with a signal being received before main_pid is updated.

Maybe there should be some signal masking/blocking or something in the critical section between fork() and PyOS_AfterFork()?
History
Date User Action Args
2022-04-11 14:58:24adminsetgithub: 69852
2015-12-11 06:25:13martin.pantersetmessages: + msg256201
versions: - Python 3.4
2015-11-20 01:58:19martin.pantersetfiles: + example.py
versions: + Python 3.5, Python 3.6
nosy: + martin.panter

messages: + msg254947
2015-11-19 14:42:42r.david.murraysetnosy: + r.david.murray
messages: + msg254898
2015-11-19 09:00:33jon orebrocreate