@@ -28,7 +28,24 @@ extern int ftime(struct timeb *);
2828#include <i86.h>
2929#else
3030#ifdef MS_WINDOWS
31+ #define WIN32_LEAN_AND_MEAN
3132#include <windows.h>
33+ #include "pythread.h"
34+
35+ /* helper to allow us to interrupt sleep() on Windows*/
36+ static HANDLE hInterruptEvent = NULL ;
37+ static BOOL WINAPI PyCtrlHandler (DWORD dwCtrlType )
38+ {
39+ SetEvent (hInterruptEvent );
40+ /* allow other default handlers to be called.
41+ Default Python handler will setup the
42+ KeyboardInterrupt exception.
43+ */
44+ return FALSE;
45+ }
46+ static long main_thread ;
47+
48+
3249#if defined(__BORLANDC__ )
3350/* These overrides not needed for Win32 */
3451#define timezone _timezone
@@ -680,7 +697,15 @@ inittime(void)
680697 Py_BuildValue ("(zz)" , _tzname [0 ], _tzname [1 ]));
681698#endif /* __CYGWIN__ */
682699#endif /* !HAVE_TZNAME || __GLIBC__ || __CYGWIN__*/
683-
700+ #ifdef MS_WINDOWS
701+ /* Helper to allow interrupts for Windows.
702+ If Ctrl+C event delivered while not sleeping
703+ it will be ignored.
704+ */
705+ main_thread = PyThread_get_thread_ident ();
706+ hInterruptEvent = CreateEvent (NULL , TRUE, FALSE, NULL );
707+ SetConsoleCtrlHandler ( PyCtrlHandler , TRUE);
708+ #endif /* MS_WINDOWS */
684709 PyStructSequence_InitType (& StructTimeType , & struct_time_type_desc );
685710 Py_INCREF (& StructTimeType );
686711 PyModule_AddObject (m , "struct_time" , (PyObject * ) & StructTimeType );
@@ -775,9 +800,27 @@ floatsleep(double secs)
775800 PyErr_SetString (PyExc_OverflowError , "sleep length is too large" );
776801 return -1 ;
777802 }
778- /* XXX Can't interrupt this sleep */
779803 Py_BEGIN_ALLOW_THREADS
780- Sleep ( (unsigned long )millisecs );
804+ /* allow sleep(0) to maintain win32 semantics, and as decreed by
805+ Guido, only the main thread can be interrupted. */
806+ if ((unsigned long )millisecs == 0 || main_thread != PyThread_get_thread_ident ())
807+ Sleep ((unsigned long )millisecs );
808+ else {
809+ DWORD rc ;
810+ ResetEvent (hInterruptEvent );
811+ rc = WaitForSingleObject (hInterruptEvent , (unsigned long )millisecs );
812+ if (rc == WAIT_OBJECT_0 ) {
813+ /* yield to make sure real Python signal handler called */
814+ Sleep (1 );
815+ Py_BLOCK_THREADS
816+ /* PyErr_SetFromErrno() does the "right thing" wrt signals
817+ if errno=EINTR
818+ */
819+ errno = EINTR ;
820+ PyErr_SetFromErrno (PyExc_IOError );
821+ return -1 ;
822+ }
823+ }
781824 Py_END_ALLOW_THREADS
782825 }
783826#elif defined(PYOS_OS2 )
0 commit comments