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: Ctrl-C doesn't work with sleepy main thread
Type: Stage:
Components: Interpreter Core Versions: Python 2.3
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: kbk Nosy List: Rhamphoryncus, anthonybaxter, doko, hyeshik.chang, kbk, mwh, skip.montanaro, tim.peters
Priority: normal Keywords:

Created on 2004-01-12 21:37 by doko, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
226547.py doko, 2004-01-12 21:37
things.diff hyeshik.chang, 2004-03-28 07:10 ceval.c patch to make ctrl-C work on Debian and FreeBSD.
ceval.c.patch kbk, 2004-11-22 19:02 updated ceval.c patch, revised comment
ceval.c.patch2 kbk, 2004-11-22 22:15 updated ceval.c patch, 2nd revision of comment
Messages (17)
msg19643 - (view) Author: Matthias Klose (doko) * (Python committer) Date: 2004-01-12 21:37
[forwarded from http://bugs.debian.org/226547]

I only have access to Debian systems ... Maybe this is
related to 846817?

I'm trying to do some basic threading with Python.
However, there are times when Ctrl-C fails to cause a
KeyboardInterrupt in the main thread.

Here is a test program that illustrates the problem. As
written, I cannot interrupt it with Ctrl-C (nothing
happens even if I hold it down). If I uncomment the
print statement in the main thread, then I can
interrupt it with Ctrl-C.

It seems like adding the print in the main thread gives
the main thread a "chance to run" where it finally
notices the signal from the Ctrl-C.  However, I
shouldn't have to use hacks like this to get this to work.

People on comp.lang.python could not reproduce this on
Fedora and some others, so I'm posting it here (maybe
some problem with Debian's libc6?).
msg19644 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2004-01-13 11:16
Logged In: YES 
user_id=6656

As the guy says in the bug report, the comp.lang.python
opinion was that this was a problem in debian!  Can someone
with a debian machine (or any other -- I can't) reproduce this?
msg19645 - (view) Author: Adam Olsen (Rhamphoryncus) Date: 2004-03-27 11:56
Logged In: YES 
user_id=12364

I use debian and can reproduce it.  Python package version 
2.3.3-6.  I also tried with python 2.2 and the bug was NOT 
present.  Package version 2.2.3-9. 
msg19646 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2004-03-27 16:00
Logged In: YES 
user_id=31435

Ctrl+C interrupts it on Win98SE -- upgrade to a real OS 
<wink>.  When odd cmdline behavior is seen on a Unixish box, 
staring at (try with and without) GNU readline is a good 
experiment.
msg19647 - (view) Author: Hyeshik Chang (hyeshik.chang) * (Python committer) Date: 2004-03-27 19:04
Logged In: YES 
user_id=55188

Nah. For my some investigation, it doesn't seem to be a
problem of GNU readline.

On my debian machine, main for loop of ceval.c:eval_frame
switches threads context for every periodic loops. Because
main threads is just running time.sleep(), it goes in this way:

1) context switches to sub thread by time.sleep()
2) entering periodic if-block and resets _Py_Tick to 100.
3) because main thread has only 1 line that runs
time.sleep(), _Py_Tick is always 97~99 for main thread.
4) goto 1)

So, Py_MakePendingCalls() will never be called from main
thread. As a result, Ctrl-C doesn't work.

Hmm. I don't have a fix for right now. How about to make
per-thread _Py_Tick?
msg19648 - (view) Author: Hyeshik Chang (hyeshik.chang) * (Python committer) Date: 2004-03-28 07:10
Logged In: YES 
user_id=55188

Here's my patch. Please review/test it. :)
msg19649 - (view) Author: Matthias Klose (doko) * (Python committer) Date: 2004-03-28 10:00
Logged In: YES 
user_id=60903

with the patch applied the example exits usually on the
second or third keystroke, never on the first ^C.
msg19650 - (view) Author: Kurt B. Kaiser (kbk) * (Python committer) Date: 2004-11-22 19:02
Logged In: YES 
user_id=149084

I can reproduce this on OpenBSD 3.4 / Python 2.4c1.

Hye-Shik Chang's fix works for me and I agree with 
his analysis.  Without the fix, 100 ctrl-c won't interrupt,
with it, a single ctrl-c interrupts every time, for 50 tries.

Also, the problem doesn't exhibit if the original test
for things_to_do is restored to block entry, as it was
before ceval.c rev 2.334  (Patch 602191)

I refreshed the patch and polished the comment.
See attached ceval.c.patch.

Assigning to Skip for review.
msg19651 - (view) Author: Skip Montanaro (skip.montanaro) * (Python triager) Date: 2004-11-22 20:04
Logged In: YES 
user_id=44345

Unless you patched an out-of-date version of ceval.c I think the
"if (things_to_do)" test in your patch is superfluous. 
Otherwise,
it looks like it will force another check the next pass of
the eval
loop.

Skip
msg19652 - (view) Author: Kurt B. Kaiser (kbk) * (Python committer) Date: 2004-11-22 20:48
Logged In: YES 
user_id=149084

Yes.  You'll notice that Py_MakePendingCalls() will
return immediately if it's not being run in the MainThread.
So what this change does is to immediately re-run it in the
next thread (if there are /still/ things_to_do) instead of
waiting (global) 100 ticks.  Without it, since the ticker never
reaches zero in MainThread using the example code
the "periodic" block won't ever get to run in MainThread.

The patch is against current cvs.
msg19653 - (view) Author: Skip Montanaro (skip.montanaro) * (Python triager) Date: 2004-11-22 21:29
Logged In: YES 
user_id=44345

I guess I didn't understand what's going on well enough.  The
inner test is required?  If so, it probably warrants a comment
since it's so close to the earlier test.
msg19654 - (view) Author: Kurt B. Kaiser (kbk) * (Python committer) Date: 2004-11-22 21:40
Logged In: YES 
user_id=149084

Please suggest an improvement to the comment I included
in my version of the patch and I'll incorporate it.

The inner test just resets the ticker if the call to
Py_MakePendingCalls() didn't resolve all the things_to_do,
which will be the case if the eval isn't executing in the
MainThread.
msg19655 - (view) Author: Skip Montanaro (skip.montanaro) * (Python triager) Date: 2004-11-22 21:51
Logged In: YES 
user_id=44345

How about:

    The inner test of things_to_do is required, as its value
might
     be changed by Py_MakePendingCalls().
msg19656 - (view) Author: Kurt B. Kaiser (kbk) * (Python committer) Date: 2004-11-22 22:15
Logged In: YES 
user_id=149084

How about this: ceval.c.patch2
msg19657 - (view) Author: Skip Montanaro (skip.montanaro) * (Python triager) Date: 2004-11-23 02:59
Logged In: YES 
user_id=44345

Looks good.  Check it in presuming that's fine for this
stage of the release cycle.
msg19658 - (view) Author: Anthony Baxter (anthonybaxter) (Python triager) Date: 2004-11-23 07:15
Logged In: YES 
user_id=29957

Seems fine to me. Please checkin (don't forget a NEWS entry!)
msg19659 - (view) Author: Kurt B. Kaiser (kbk) * (Python committer) Date: 2004-11-23 18:16
Logged In: YES 
user_id=149084

NEWS   rev 1.1191
ceval.c  rev 2.419
History
Date User Action Args
2022-04-11 14:56:02adminsetgithub: 39809
2004-01-12 21:37:57dokocreate