[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