[Python-bugs-list] [ python-Bugs-581232 ] [Windows] Can not interrupt time.sleep()

noreply@sourceforge.net noreply@sourceforge.net
Sun, 14 Jul 2002 18:09:09 -0700


Bugs item #581232, was opened at 2002-07-14 03:59
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=581232&group_id=5470

Category: Python Library
Group: Platform-specific
Status: Open
>Resolution: Accepted
Priority: 5
Submitted By: Mark Hammond (mhammond)
Assigned to: Mark Hammond (mhammond)
Summary: [Windows] Can not interrupt time.sleep()

Initial Comment:
As nagged by Tim - time.sleep(10000) can not be
interrupted by Ctrl+C on Windows.  Attaching a patch to
fix this.

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

>Comment By: Tim Peters (tim_one)
Date: 2002-07-14 21:09

Message:
Logged In: YES 
user_id=31435

Well, there's no Sleep on earth long enough to guarantee 
that some other specific thread got a timeslice, so maybe 
that's the best that can be done.

I'm not sure what you mean when you say that the main 
thread sees KeyboardInterrupt on Linux.  In sleeper.py?  I 
expect the main thread to be hung, waiting to acquire a 
lock that will never be released (when a thread in 
sleeper.py is killed via IOError, it never releases its lock, 
and the main thread should hang trying to acquire it).  A 
lock.acquire() shouldn't be interruptible by Ctrl+C, so 
there's a Linux bug here if the main thread isn't hung.

Anyway, that's irrelevant to this patch, so Accepted and 
back to you.  Reformat so that lines don't go beyond 
column 79?  Also please write some Misc/NEWS blurbs for 
the things you checked in today.  Thanks!

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

Comment By: Mark Hammond (mhammond)
Date: 2002-07-14 19:21

Message:
Logged In: YES 
user_id=14198

I think we are faced with a timing problem for signals.  As
far as I can tell, this follows the same code path as other
platforms.

* Interrupted sleep detected.
* Errno of EINTR set.
* PyErr_SetFromErrNo handles EINTR as a special case - if
Py_CheckSignals() returns TRUE, it leaves KeyboardInterrupt
current and discards the current exception.

So, what this means is that *one* interrupted thread will
see the KeyboardInterrupt exception and all others will see
OSError(EINTR).

Indeed, this is exactly what I see for Linux - the main
thread sees the KeyboardInterrupt, while all other threads
see OSError(EINTR).

My guess is that the Sleep(1) I added is not long enough -
that on Win9x the signal handler has not yet been called,
therefore all threads see OSError.  Is this possible?



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

Comment By: Tim Peters (tim_one)
Date: 2002-07-14 19:09

Message:
Logged In: YES 
user_id=31435

This definitely makes time.sleep() interruptible on Win98, 
but I don't think it's quite there yet.  Playing with it by 
hand, one time I saw

IOError: [Errno 4] Interrupted function call

instead of KeyboardInterrupt when hitting Ctrl+C in an 
interactive shell.  The attached sleeper.py provokes lots of 
those by using threads (hit Ctrl+C within 10 seconds of 
starting it).

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

Comment By: Mark Hammond (mhammond)
Date: 2002-07-14 10:46

Message:
Logged In: YES 
user_id=14198

... need uninterrupted sleep <wink>.  Please ignore the
Ctrl+Break comments - I had my bugs mixed up.  Rest is still
valid tho.

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

Comment By: Mark Hammond (mhammond)
Date: 2002-07-14 10:38

Message:
Logged In: YES 
user_id=14198

Here we go - a better patch.  This delivers the exact same
multi-threaded semantics as my Linux build.

Re Ctrl+Break - no argument from me - my "if deemed broken"
was meant to imply that!  Win9x Ctrl+Break must be the same
as Win2k - I seemed to recall on Win9x it behaved like a
Ctrl+C.  No 9x even booted to check, and I don't really care
<wink>

FWIW, my test script:
import time, threading, thread

def sleeper():
    try:
        time.sleep(30)
    finally:
        msg = "Thread %d dieing" % (thread.get_ident(),)
        print msg

threads=[]
for i in range(2):
    t=threading.Thread(target=sleeper)
    t.start()
    threads.append(t)
print "sleeping"
try:
    time.sleep(30)
finally:
    print "waiting"
    [t.join for t in threads]
    print "final short sleep"
    time.sleep(2)


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

Comment By: Mark Hammond (mhammond)
Date: 2002-07-14 04:05

Message:
Logged In: YES 
user_id=14198

Poo - not a thread-safe patch.  I will think about this some
more tomorrow.

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

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