python / cpython

The Python programming language
https://www.python.org
Other
62.69k stars 30.06k forks source link

Ctrl-C doesn't work with sleepy main thread #39809

Closed doko42 closed 19 years ago

doko42 commented 20 years ago
BPO 875692
Nosy @mwhudson, @tim-one, @smontanaro, @doko42, @kbkaiser, @hyeshik
Files
  • 226547.py
  • things.diff: ceval.c patch to make ctrl-C work on Debian and FreeBSD.
  • ceval.c.patch: updated ceval.c patch, revised comment
  • ceval.c.patch2: updated ceval.c patch, 2nd revision of comment
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields: ```python assignee = 'https://github.com/kbkaiser' closed_at = created_at = labels = ['interpreter-core'] title = "Ctrl-C doesn't work with sleepy main thread" updated_at = user = 'https://github.com/doko42' ``` bugs.python.org fields: ```python activity = actor = 'kbk' assignee = 'kbk' closed = True closed_date = None closer = None components = ['Interpreter Core'] creation = creator = 'doko' dependencies = [] files = ['1163', '1164', '1165', '1166'] hgrepos = [] issue_num = 875692 keywords = [] message_count = 17.0 messages = ['19643', '19644', '19645', '19646', '19647', '19648', '19649', '19650', '19651', '19652', '19653', '19654', '19655', '19656', '19657', '19658', '19659'] nosy_count = 8.0 nosy_names = ['mwh', 'tim.peters', 'skip.montanaro', 'anthonybaxter', 'doko', 'kbk', 'hyeshik.chang', 'Rhamphoryncus'] pr_nums = [] priority = 'normal' resolution = 'fixed' stage = None status = 'closed' superseder = None type = None url = 'https://bugs.python.org/issue875692' versions = ['Python 2.3'] ```

    doko42 commented 20 years ago

    [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?).

    mwhudson commented 20 years ago

    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?

    8d8a8db7-faf5-4c09-a2a3-2697dbaf0735 commented 20 years ago

    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.

    tim-one commented 20 years ago

    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.

    hyeshik commented 20 years ago

    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?

    hyeshik commented 20 years ago

    Logged In: YES user_id=55188

    Here's my patch. Please review/test it. :)

    doko42 commented 20 years ago

    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.

    kbkaiser commented 19 years ago

    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.

    smontanaro commented 19 years ago

    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

    kbkaiser commented 19 years ago

    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.

    smontanaro commented 19 years ago

    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.

    kbkaiser commented 19 years ago

    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.

    smontanaro commented 19 years ago

    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().

    kbkaiser commented 19 years ago

    Logged In: YES user_id=149084

    How about this: ceval.c.patch2

    smontanaro commented 19 years ago

    Logged In: YES user_id=44345

    Looks good. Check it in presuming that's fine for this stage of the release cycle.

    1a90d5ba-e091-4ed6-a644-41c5568983da commented 19 years ago

    Logged In: YES user_id=29957

    Seems fine to me. Please checkin (don't forget a NEWS entry!)

    kbkaiser commented 19 years ago

    Logged In: YES user_id=149084

    NEWS rev 1.1191 ceval.c rev 2.419