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: TypeError/hang inside of Time.Sleep() when _thread.interrupt_main()
Type: behavior Stage: resolved
Components: Versions: Python 3.6
process
Status: closed Resolution: duplicate
Dependencies: Superseder: _thread.interrupt_main() errors if SIGINT handler in SIG_DFL, SIG_IGN
View: 23395
Assigned To: Nosy List: AR-Kareem, eryksun
Priority: normal Keywords:

Created on 2020-12-24 17:29 by AR-Kareem, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (5)
msg383695 - (view) Author: AR Kareem (AR-Kareem) Date: 2020-12-24 17:29
I get a random TypeError exception thrown whenever I interrupt/kill a sleeping parent thread from a child thread but ONLY if the python script was invoked by a shell script with an & argument to make it run in the background. (this is in vanilla python)

This doesn't happen if invoked 

(1) in command line
(2) in command line with &
(3) in shell script (without &)

Only in shell script with &.

Here is the python script named psc.py https://pastebin.com/raw/KZQptCMr
And here is the shell script named ssc.sh https://pastebin.com/raw/QQzs4Tpz that when ran will run the python script and cause the strange behaviour

Here is the output I'm seeing: -------------------
parent looping
child interrupting parent
why would I ever catch a TypeError?
Traceback (most recent call last):
  File "m.py", line 17, in <module>
    time.sleep(1)
TypeError: 'int' object is not callable

Here is the output I'm expecting: --------------------
parent looping
child interrupting parent
caught interruption raised from user or child thread :)

Another unexpected behaviour might be that python suddenly hangs.

Here is a stackoverflow question raised on this issue with discussion in the comments https://stackoverflow.com/questions/65440353/python-time-sleep1-raises-typeerror?noredirect=1#comment115697237_65440353
msg383717 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2020-12-25 05:01
When a process executes in the background from a non-interactive bash script, the initial handler for SIGINT is SIG_IGN (ignore). Prior to 3.7, _thread.interrupt_main() tries to trip SIGINT even when the C handler is set to SIG_IGN. But Python uses an integer constant for SIG_IGN (named IgnoreHandler in Modules/signalmodule.c), and trying to call it is a TypeError. This was fixed in 3.7+ to resolve bpo-23395. You've flagged this as an issue with 3.7, but the Stack Overflow question is for 3.6. If you're actually using 3.6 instead of 3.7, this issue should be closed as a duplicate.

To manually enable the normal KeyboardInterrupt exception, call signal.signal(signal.SIGINT, signal.default_int_handler).
msg383731 - (view) Author: AR Kareem (AR-Kareem) Date: 2020-12-25 09:42
My apologies, I meant to flag it as 3.6 instead of 3.7.

I see what's happening now, and thanks for providing the correct way to raise a KeyboardInterrupt.

Correctly flagged as 3.6 and closed.

Thanks.
msg383734 - (view) Author: AR Kareem (AR-Kareem) Date: 2020-12-25 11:03
Shouldn't the behaviour for _thread.interrupt_main() be always to interrupt the main thread. 

I would expect that if a child thread uses _thread.interrupt_main() that the main thread be interrupted regardless of how the python script was invoked.

Wouldn't it be more reasonable to make _thread.interrupt_main() always raise a SIGINT? I'm not sure if this is technically considered a bug or not, but it seems that it's not functioning as intended even in Python 3.7
msg388972 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2021-03-17 21:45
> Shouldn't the behaviour for _thread.interrupt_main() be always to 
> interrupt the main thread. 

The underlying C API function, PyErr_SetInterrupt(), simulates SIGINT without actually sending the signal to the process via kill() or raise(), but the doc string of interrupt_main() doesn't explain this, or at least it didn't used to. bpo-43356 generalized _thread.interrupt_main() to support simulating any available signal, and hopefully the new doc string [1] clarifies the intent.

---

[1] https://github.com/python/cpython/blob/9976834f807ea63ca51bc4f89be457d734148682/Modules/_threadmodule.c#L1194
History
Date User Action Args
2022-04-11 14:59:39adminsetgithub: 86896
2021-03-17 21:45:01eryksunsetstatus: open -> closed
superseder: _thread.interrupt_main() errors if SIGINT handler in SIG_DFL, SIG_IGN
messages: + msg388972

stage: resolved
2020-12-25 11:03:58AR-Kareemsetmessages: + msg383734
2020-12-25 09:42:32AR-Kareemsetresolution: duplicate
messages: + msg383731
versions: + Python 3.6, - Python 3.7
2020-12-25 05:01:43eryksunsettype: behavior

messages: + msg383717
nosy: + eryksun
2020-12-24 19:22:58AR-Kareemsettitle: TypeError in Time.Sleep when invoked from shell script background -> TypeError/hang inside of Time.Sleep() when _thread.interrupt_main()
2020-12-24 17:29:09AR-Kareemcreate