@@ -35,6 +35,9 @@ int (*PyOS_InputHook)(void) = NULL;
3535static int
3636my_fgets (char * buf , int len , FILE * fp )
3737{
38+ #ifdef MS_WINDOWS
39+ HANDLE hInterruptEvent ;
40+ #endif
3841 char * p ;
3942 int err ;
4043 while (1 ) {
@@ -50,32 +53,28 @@ my_fgets(char *buf, int len, FILE *fp)
5053 return 0 ; /* No error */
5154 err = errno ;
5255#ifdef MS_WINDOWS
53- /* In the case of a Ctrl+C or some other external event
54- interrupting the operation:
55- Win2k/NT: ERROR_OPERATION_ABORTED is the most recent Win32
56- error code (and feof() returns TRUE).
57- Win9x: Ctrl+C seems to have no effect on fgets() returning
58- early - the signal handler is called, but the fgets()
59- only returns "normally" (ie, when Enter hit or feof())
56+ /* Ctrl-C anywhere on the line or Ctrl-Z if the only character
57+ on a line will set ERROR_OPERATION_ABORTED. Under normal
58+ circumstances Ctrl-C will also have caused the SIGINT handler
59+ to fire which will have set the event object returned by
60+ _PyOS_SigintEvent. This signal fires in another thread and
61+ is not guaranteed to have occurred before this point in the
62+ code.
63+
64+ Therefore: check whether the event is set with a small timeout.
65+ If it is, assume this is a Ctrl-C and reset the event. If it
66+ isn't set assume that this is a Ctrl-Z on its own and drop
67+ through to check for EOF.
6068 */
6169 if (GetLastError ()== ERROR_OPERATION_ABORTED ) {
62- /* Signals come asynchronously, so we sleep a brief
63- moment before checking if the handler has been
64- triggered (we cant just return 1 before the
65- signal handler has been called, as the later
66- signal may be treated as a separate interrupt).
67- */
68- Sleep (1 );
69- if (PyOS_InterruptOccurred ()) {
70+ hInterruptEvent = _PyOS_SigintEvent ();
71+ switch (WaitForSingleObject (hInterruptEvent , 10 )) {
72+ case WAIT_OBJECT_0 :
73+ ResetEvent (hInterruptEvent );
7074 return 1 ; /* Interrupt */
75+ case WAIT_FAILED :
76+ return -2 ; /* Error */
7177 }
72- /* Either the sleep wasn't long enough (need a
73- short loop retrying?) or not interrupted at all
74- (in which case we should revisit the whole thing!)
75- Logging some warning would be nice. assert is not
76- viable as under the debugger, the various dialogs
77- mean the condition is not true.
78- */
7978 }
8079#endif /* MS_WINDOWS */
8180 if (feof (fp )) {
@@ -94,7 +93,7 @@ my_fgets(char *buf, int len, FILE *fp)
9493#endif
9594 if (s < 0 )
9695 return 1 ;
97- /* try again */
96+ /* try again */
9897 continue ;
9998 }
10099#endif
0 commit comments