[Python-bugs-list] [ python-Bugs-439992 ] [win32] KeyboardInterrupt Not Caught

noreply@sourceforge.net noreply@sourceforge.net
Sun, 14 Jul 2002 16:14:02 -0700


Bugs item #439992, was opened at 2001-07-10 19:24
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=439992&group_id=5470

Category: Python Interpreter Core
Group: Platform-specific
>Status: Closed
>Resolution: Fixed
Priority: 5
Submitted By: Nobody/Anonymous (nobody)
Assigned to: Mark Hammond (mhammond)
Summary: [win32] KeyboardInterrupt Not Caught

Initial Comment:
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

----------------------------------------------------------------------

>Comment By: Mark Hammond (mhammond)
Date: 2002-07-15 09:14

Message:
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


----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2002-07-15 07:55

Message:
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.

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2002-07-15 07:33

Message:
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.

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2002-07-14 17:05

Message:
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>.

----------------------------------------------------------------------

Comment By: Mark Hammond (mhammond)
Date: 2002-07-14 16:50

Message:
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)


----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2002-07-14 12:30

Message:
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>).

----------------------------------------------------------------------

Comment By: Mark Hammond (mhammond)
Date: 2002-07-14 11:25

Message:
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?

----------------------------------------------------------------------

Comment By: Skip Montanaro (montanaro)
Date: 2002-03-10 12:41

Message:
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


----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2001-12-12 17:08

Message:
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.

----------------------------------------------------------------------

Comment By: Guido van Rossum (gvanrossum)
Date: 2001-12-12 16:34

Message:
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?

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2001-08-08 01:51

Message:
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.

----------------------------------------------------------------------

Comment By: Guido van Rossum (gvanrossum)
Date: 2001-08-07 23:59

Message:
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.

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=439992&group_id=5470