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: [win32] KeyboardInterrupt Not Caught
Type: Stage:
Components: Interpreter Core Versions:
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: mhammond Nosy List: gvanrossum, mhammond, skip.montanaro, tim.peters
Priority: normal Keywords:

Created on 2001-07-10 09:24 by anonymous, last changed 2022-04-10 16:04 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
myreadline.patch mhammond, 2002-07-14 01:25 Patch that catches Ctrl+C exceptions better
Messages (13)
msg5324 - (view) Author: Nobody/Anonymous (nobody) Date: 2001-07-10 09:24
The following program, run under unix (FreeBSD 4.3) and Windows 2000 SP2
with the command line:  python test.py

In both cases, running python 2.1.

The program works as expected under unix and IDLE on Windows 2000, but it
does *not* catch the interrupt in the command line version of Win32 python...
i.e., The traceback message appears rather than my "Leaving Dodge..." message.


while 1:
    try:
        x = raw_input().upper()
        print x
    except KeyboardInterrupt:
        print "Leaving Dodge...\n"
        break
msg5325 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2001-08-07 13:59
Logged In: YES 
user_id=6380

Yes, I'm afraid signal handling doesn't always work on
Windows.
I don't know Windows enough to understand how to fix this.
msg5326 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2001-08-07 15:51
Logged In: YES 
user_id=31435

For posterity, a delightfully confused section of 
MS's "signal" docs:

"""
Note SIGINT is not supported for any Win32 application 
including Windows NT and Windows 95. When a CTRL+C 
interrupt occurs, Win32 operating systems generate a new 
thread to specifically handle that interrupt. This can 
cause a single-thread application such as UNIX, to become 
multithreaded, resulting in unexpected behavior. 
"""

I kid you not.
msg5327 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2001-12-12 05:34
Logged In: YES 
user_id=6380

Shall we close this as Won't Fix? Is there a point in
keeping it open while we know we can't fix it?
msg5328 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2001-12-12 06:08
Logged In: YES 
user_id=31435

Umm, I have no idea whether it can be fixed.  Who was this 
assigned to?  Assigning to MarkH in case he has an idea.
msg5329 - (view) Author: Skip Montanaro (skip.montanaro) * (Python triager) Date: 2002-03-10 01:41
Logged In: YES 
user_id=44345

just a note to remind folks that GvR suggested closing
this as "won't fix" a few months ago.  Seems like it's
still the correct course unless MS has changed Windows
dramtically in the intervening interval. -skip
msg5330 - (view) Author: Mark Hammond (mhammond) * (Python committer) Date: 2002-07-14 01:25
Logged In: YES 
user_id=14198

This is an interesting one :)

When Python is inside an fgets() and a Ctrl+C is hit, we see
two things:
* fgets() returns immediately with an "eof" condition. 
There is no errno set to indicate the interrupt like there
is on *nix.
* The signal handler is called asynchronously on another thread.

So what the user sees is:
* The EOF flag causes Python to raise an EOFError when
Ctrl+C is pressed.
* When the signal is finally triggered, Python sees
*another* exception, this time a keyboard interrupt.

For example, the following code:
import time, sys
while 1:
    try:
        x = raw_input().upper()
        print x
    except KeyboardInterrupt:
        print "Done"
        break
    except EOFError:
        print "EOF"
        break

will *usually* print "EOF" when Ctrl+C is pressed.

I have determined that when Ctrl+C is pressed, the Win32
function GetLastError() returns ERROR_OPERATION_ABORTED.  By
using this undocumented feature, I have created a patch that
makes Ctrl+C work as it does on *nix.

One side effect is that Ctrl+C in an interactive Python
session no longer terminates the process - just like *nix,
it now prints "KeyboardInterrupt" then returns to the
interactive prompt.

Tim - what say you on this?
msg5331 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2002-07-14 02:30
Logged In: YES 
user_id=31435

I don't object to trying to make it better <wink>.  I'm 
confused by a couple of things, though.

1. You said

"""
One side effect is that Ctrl+C in an interactive Python
session no longer terminates the process - just like *nix,
it now prints "KeyboardInterrupt" then returns to the
interactive prompt.
"""

I use Ctrl+C in interactive sessions on Windows a lot, and 
it never terminates the process -- KeyboardInterrupt is 
what I get now.  I don't recall that being specific to Win9x, 
although maybe it is.

2. There's something fishy about Python's time.sleep() on 
Windows too.  If I run this C program on Windows:

#include <windows.h>
int main() { Sleep(10000); return 0; }

then it quits the instant I hit Ctrl+C.  But if I do

time.sleep(10)

from Python and hit Ctrl+C, it waits until 10 seconds are 
up before proceeding and displaying KeyboardInterrupt.

Since time.sleep() just calls Sleep() on Windows, this has 
always baffled me (but not enough to investigate, and 
you're on a roll <wink>).
msg5332 - (view) Author: Mark Hammond (mhammond) * (Python committer) Date: 2002-07-14 06:50
Logged In: YES 
user_id=14198

Re Ctrl+C - it is indeed Win9x specific and I should have
remembered that.  NT/2k etc sees pretty much instant death.
 My investigations with the debugger show that this "death"
was actually normal termination due to eof() being detected
(rather than the Ctrl+C)

Re sleep - the problem is that we install a signal handler.
 The default signal handler aborts the process
asynchronously, just like Ctrl+Break still does for NT
(which also can be fixed if deemed broken. IIRC, 9x and NT
still have different Ctrl+Break handling.)

Installing a signal handler disables the default.  The
following C program behaves like Python:

#include <signal.h>
#include <windows.h>
static void signal_handler(int sig_num) {}

int main() {
    signal(SIGINT, signal_handler);    
    Sleep(10000); return 0; 
}

but I may even try to fix that <wink>.  If I do, then it
will be quite a different solution than for the patch
proposed here.

Tim - I don't have MSVC on 9x handy here, but would be
interested to see how myreadline.c works on Win9x with a
Ctrl+C.  As the comments imply, on NT we see feof()
returning true, and errno set to something useless (file not
found IIRC)
msg5333 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2002-07-14 07:05
Logged In: YES 
user_id=31435

Ah, signal handlers.  Mmm.  It would be good to do 
something to let Ctrl+C interrupt a Sleep() in Python.  The 
timemodule.c code currently has a disappointed XXX 
comment claiming that Windows Sleep isn't interruptible.

About Ctrl+Break, please don't even think about fixing it.  
It's the only convenient way we have to kill Python console 
programs that have gone insane, typically in a blocking 
operation that's never going to get what it's waiting for, and 
especially if multiple threads are involved.  Note that, a few 
releases ago, I added SIGBREAK to the Python signal 
module on Windows, and the NEWS file shows how a user 
can exploit that in Python code so that Ctrl+Break acts 
just like Ctrl+C -- if that's what they want to do.

I'll give your patch a try tomorrow!  It's too late here now, in 
the decent part of the world <wink>.
msg5334 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2002-07-14 21:33
Logged In: YES 
user_id=31435

Just noting that, before trying your patch, your test 
program doesn't work the same way on Win98:  hitting 
Ctrl+C has no effect, *until* ENTER is hit.  Then it always 
takes the "Done" branch.  Similarly, the OP's test program 
always prints "Leaving Dodge ..." in response to Ctrl+C, 
and again it waits until ENTER is hit..

Peeking in the code, p is never NULL, Ctrl+C or not.  In 
your test program, if I type

a b Ctrl+C c d ENTER

then p points to the 3-byte string "cd\n", and feof(fp) is 
false.  We get the KeyboardInterrupt then by virtue of 
things_to_do being true back in ceval.
msg5335 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2002-07-14 21:55
Logged In: YES 
user_id=31435

I marked this Accepted.  It doesn't appear to do anything 
on Win98 (p is never NULL there, except on EOF), so if it 
helps on Win2K, cool.
msg5336 - (view) Author: Mark Hammond (mhammond) * (Python committer) Date: 2002-07-14 23:14
Logged In: YES 
user_id=14198

Checking in myreadline.c;
/cvsroot/python/python/dist/src/Parser/myreadline.c,v  <-- 
myreadline.c
new revision: 2.27; previous revision: 2.26
done
History
Date User Action Args
2022-04-10 16:04:11adminsetgithub: 34717
2001-07-10 09:24:21anonymouscreate