[Python-bugs-list] [ python-Bugs-581232 ] [Windows] Can not interrupt time.sleep()
noreply@sourceforge.net
noreply@sourceforge.net
Sun, 14 Jul 2002 19:07:57 -0700
Bugs item #581232, was opened at 2002-07-14 17: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: Mark Hammond (mhammond)
Date: 2002-07-15 12:07
Message:
Logged In: YES
user_id=14198
While there is no sleep long enough to guarantee anything,
we could make it more likely <wink>. How about we add an
order of magnitude, and sleep for 10ms? There is no way
this could be considered time critical code.
I'm a little confused by your statement:
> (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)
threading.py, Thread.__bootstrap(), via __stop() seems to
ensure that the lock is released in the face of
exceptions. I don't see how a failing thread (IOError or
otherwise) deadlocks when joining on it.
Re Linux etc. I didn't realize I was using Python 1.5.2!!
With that version I saw:
sleeping
Thread 2051 dieing
Exception in thread Thread-2:
Traceback (innermost last):
...
File "delme.py", line 5, in sleeper
time.sleep(30)
IOError: [Errno 4] Interrupted system call
Thread 1026 dieing
Exception in thread Thread-1:
Traceback (innermost last):
...
File "delme.py", line 5, in sleeper
time.sleep(30)
IOError: [Errno 4] Interrupted system call
waiting
Traceback (innermost last):
File "delme.py", line 17, in ?
time.sleep(30)
KeyboardInterrupt
However, with CVS Python on Linux, I see this:
sleeping
waiting
Thread 1026 dieing
Thread 2051 dieing
Traceback (most recent call last):
File "/home/skip/temp/delme.py", line 18, in ?
time.sleep(30)
KeyboardInterrupt
[Ignore line number differences!]
NOTE: This only happens *after* the thread's sleep() calls
have expired. ie, Ctrl+C does *not* appear to interrupt
each thread any more, just the main thread. Further,
neither 1.5.2 nor CVS Python seem to deadlock at exit
regardless of how often I hit Ctrl+C.
sigh - I am not sure what the intent for Linux is any more
:( So my specific questions:
* In the face of this information, is my patch still
reasonable? Should we clarify the "most desirable"
semantics (assuming the platform is capable) first?
* Should this apparent linux change be brought up?
----------------------------------------------------------------------
Comment By: Tim Peters (tim_one)
Date: 2002-07-15 11: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-15 09: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-15 09: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-15 00: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-15 00: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 18: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