diff -r 94ec4d8cf104 Modules/_tkinter.c --- a/Modules/_tkinter.c Fri Jan 23 17:30:26 2015 -0500 +++ b/Modules/_tkinter.c Sat Jan 24 13:39:26 2015 +0900 @@ -24,6 +24,7 @@ #include "Python.h" #include +#include #ifdef WITH_THREAD #include "pythread.h" @@ -3291,9 +3292,18 @@ static PyThreadState *event_tstate = NULL; #endif +static int interrupted = 0; + +static void +sigint_handler(int sig) +{ + interrupted = 1; +} + static int EventHook(void) { + PyOS_sighandler_t py_sigint_handler = NULL; #ifndef MS_WINDOWS int tfile; #endif @@ -3306,7 +3316,8 @@ tfile = fileno(stdin); Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL); #endif - while (!errorInCmd && !stdin_ready) { + py_sigint_handler = PyOS_setsig(SIGINT, sigint_handler); + while (!errorInCmd && !stdin_ready && !interrupted) { int result; #ifdef MS_WINDOWS if (_kbhit()) { @@ -3322,7 +3333,7 @@ result = Tcl_DoOneEvent(TCL_DONT_WAIT); tcl_tstate = NULL; - if(tcl_lock)PyThread_release_lock(tcl_lock); + if (tcl_lock) PyThread_release_lock(tcl_lock); if (result == 0) Sleep(Tkinter_busywaitinterval); Py_END_ALLOW_THREADS @@ -3333,6 +3344,7 @@ if (result < 0) break; } + PyOS_setsig(SIGINT, py_sigint_handler); #ifndef MS_WINDOWS Tcl_DeleteFileHandler(tfile); #endif @@ -3345,7 +3357,13 @@ #ifdef WITH_THREAD PyEval_SaveThread(); #endif - return 0; + if (interrupted) { + interrupted = 0; + errno = EINTR; + raise(SIGINT); + return -1; + } + return 1; } #endif diff -r 94ec4d8cf104 Modules/readline.c --- a/Modules/readline.c Fri Jan 23 17:30:26 2015 -0500 +++ b/Modules/readline.c Sat Jan 24 13:39:26 2015 +0900 @@ -966,7 +966,6 @@ #if defined(HAVE_RL_CALLBACK) && defined(HAVE_SELECT) - static char *completed_input_string; static void rlhandler(char *text) @@ -996,22 +995,15 @@ while (completed_input_string == not_done_reading) { int has_input = 0; - while (!has_input) - { struct timeval timeout = {0, 100000}; /* 0.1 seconds */ - - /* [Bug #1552726] Only limit the pause if an input hook has been - defined. */ - struct timeval *timeoutp = NULL; - if (PyOS_InputHook) - timeoutp = &timeout; - FD_SET(fileno(rl_instream), &selectset); + if(PyOS_InputHook) has_input = PyOS_InputHook(); + else { + int fd = fileno(rl_instream); + FD_SET(fd, &selectset); /* select resets selectset if no input was available */ - has_input = select(fileno(rl_instream) + 1, &selectset, - NULL, NULL, timeoutp); - if(PyOS_InputHook) PyOS_InputHook(); + has_input = select(fd + 1, &selectset, NULL, NULL, NULL); } - if(has_input > 0) { + if(has_input >= 0) { rl_callback_read_char(); } else if (errno == EINTR) { @@ -1056,6 +1048,7 @@ { PyOS_sighandler_t old_inthandler; char *p; + int old_timeout; *signal = 0; @@ -1069,8 +1062,10 @@ *signal = 1; return NULL; } + old_timeout = rl_set_keyboard_input_timeout(0); rl_event_hook = PyOS_InputHook; p = readline(prompt); + rl_set_keyboard_input_timeout(old_timeout); PyOS_setsig(SIGINT, old_inthandler); return p; diff -r 94ec4d8cf104 Parser/myreadline.c --- a/Parser/myreadline.c Fri Jan 23 17:30:26 2015 -0500 +++ b/Parser/myreadline.c Sat Jan 24 13:39:26 2015 +0900 @@ -45,40 +45,43 @@ #endif while (1) { - if (PyOS_InputHook != NULL) - (void)(PyOS_InputHook)(); - errno = 0; - clearerr(fp); - p = fgets(buf, len, fp); - if (p != NULL) - return 0; /* No error */ + int has_input; + if (PyOS_InputHook) has_input = PyOS_InputHook(); + else has_input = 1; + if (has_input >= 0) { + errno = 0; + clearerr(fp); + p = fgets(buf, len, fp); + if (p != NULL) + return 0; /* No error */ #ifdef MS_WINDOWS - /* 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. + /* 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) { - for (i = 0; i < 10; i++) { - if (PyOS_InterruptOccurred()) - return 1; - Sleep(1); + 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) { + for (i = 0; i < 10; i++) { + if (PyOS_InterruptOccurred()) + return 1; + Sleep(1); + } + } +#endif /* MS_WINDOWS */ + if (feof(fp)) { + clearerr(fp); + return -1; /* EOF */ } } -#endif /* MS_WINDOWS */ - if (feof(fp)) { - clearerr(fp); - return -1; /* EOF */ - } #ifdef EINTR - if (errno == EINTR) { + else if (errno == EINTR) { int s; #ifdef WITH_THREAD PyEval_RestoreThread(_PyOS_ReadlineTState);