diff options
author | Tim Golden <mail@timgolden.me.uk> | 2012-06-29 17:27:08 (GMT) |
---|---|---|
committer | Tim Golden <mail@timgolden.me.uk> | 2012-06-29 17:27:08 (GMT) |
commit | b92b757eed4aeac9b238f1fa355038e200e9e0d3 (patch) | |
tree | c82134c14af25477b366c4880dc38eca5d252de5 | |
parent | 5b5619f717be2a712c05d6c63a0ca4184f263aee (diff) | |
download | cpython-b92b757eed4aeac9b238f1fa355038e200e9e0d3.zip cpython-b92b757eed4aeac9b238f1fa355038e200e9e0d3.tar.gz cpython-b92b757eed4aeac9b238f1fa355038e200e9e0d3.tar.bz2 |
Issue #1677: Handle better a race condition between the interactive interpreter and
the Ctrl-C signal handler on Windows
-rw-r--r-- | Parser/myreadline.c | 37 |
1 files changed, 15 insertions, 22 deletions
diff --git a/Parser/myreadline.c b/Parser/myreadline.c index cb1cf0f..f0b51f8 100644 --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -36,6 +36,7 @@ static int my_fgets(char *buf, int len, FILE *fp) { char *p; + int i; int err; while (1) { if (PyOS_InputHook != NULL) @@ -50,32 +51,24 @@ my_fgets(char *buf, int len, FILE *fp) return 0; /* No error */ err = errno; #ifdef MS_WINDOWS - /* In the case of a Ctrl+C or some other external event - interrupting the operation: - Win2k/NT: ERROR_OPERATION_ABORTED is the most recent Win32 - error code (and feof() returns TRUE). - Win9x: Ctrl+C seems to have no effect on fgets() returning - early - the signal handler is called, but the fgets() - only returns "normally" (ie, when Enter hit or feof()) + /* Ctrl-C anywhere on the line or Ctrl-Z if the only character + on a line will set ERROR_OPERATION_ABORTED. Under normal + circumstances Ctrl-C will also have caused the SIGINT handler + to fire. This signal fires in another thread and is not + guaranteed to have occurred before this point in the code. + + Therefore: check in a small loop to see if the trigger has + fired, in which case assume this is a Ctrl-C event. If it + hasn't fired within 10ms assume that this is a Ctrl-Z on its + own or that the signal isn't going to fire for some other + reason and drop through to check for EOF. */ if (GetLastError()==ERROR_OPERATION_ABORTED) { - /* Signals come asynchronously, so we sleep a brief - moment before checking if the handler has been - triggered (we cant just return 1 before the - signal handler has been called, as the later - signal may be treated as a separate interrupt). - */ + for (i = 0; i < 10; i++) { + if (PyOS_InterruptOccurred()) + return 1; Sleep(1); - if (PyOS_InterruptOccurred()) { - return 1; /* Interrupt */ } - /* Either the sleep wasn't long enough (need a - short loop retrying?) or not interrupted at all - (in which case we should revisit the whole thing!) - Logging some warning would be nice. assert is not - viable as under the debugger, the various dialogs - mean the condition is not true. - */ } #endif /* MS_WINDOWS */ if (feof(fp)) { |