469,572 Members | 1,210 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,572 developers. It's quick & easy.

Re: Win32 trouble with threading, signals, and sleep()

Lowell Alleman wrote:
I'm running into this issue on Windows with the follow exception at
the time when the signal handler is called:

Traceback (most recent call last):
...
self.done.wait(30)
File "D:\Python24\lib\threading.py", line 348, in wait
self.__cond.wait(timeout)
File "D:\Python24\lib\threading.py", line 222, in wait
_sleep(delay)
IOError: [Errno 4] Interrupted function call

Well you've certainly picked a ticklish area to run
into problems with ;). First, forget about the
threading aspects for the moment. AFAICT the smallest
program which reproduces your problem is:

<code>
import signal
import time

def handler (*args):
pass

signal.signal(signal.SIGBREAK, handler)
time.sleep (10)

</code>

Now run that and do a ctrl-break somewhere in
that time.sleep. Sure enough...

<output>
Traceback (most recent call last):
File "C:\data\temp\sig3.py", line 8, in <module>
time.sleep (10)
IOError: [Errno 4] Interrupted function call

</output>

Under the covers, the sleep function is implemented
as a WaitForSingleObject call with a timeout. The
object being waited on is an anonymous event which
is set from a console ctrl handler when one of
those interrupts happens (ctrl-c / ctrl-break /
shutdown). This makes sure that the (otherwise
blocking) sleep can be interrupted. Something
like this:

<code>
import win32api
import win32event

hEvent = win32event.CreateEvent (None, 1, 0, None)
def handler (*args):
win32event.PulseEvent (hEvent)
return True

win32api.SetConsoleCtrlHandler (handler, 1)
#
# This line is basically the sleep happening
#
win32event.WaitForSingleObject (hEvent, 10000)

</code>

For reasons which I'm not aware of, the code
recognises that the interrupt has fired and
sets the WSAEINTR error code, which is the
IOError 4 which you're seeing, and then exits.
EINTR is usually issued when a blocking call
is cancelled explicitly, so presumably this
is considered a simulation of that. Not sure.

What happens now is that control passes
back out to the routine which called the
sleep. But... an exception condition has
been set inside the sleep call and is now
raised, appearing to come from within the
routine which called sleep.

Clear?

You could obviously continue to catch the
exception. Alternatively,
I think your best bet, as long as you can make
it work with the threads, is to install your
own console ctrl handler. Note that the docs
for this specify that:

"When the signal is received, the system creates
a new thread in the process to execute the function."

So you'll need to be quite careful to make your
code thread-safe. But it should work. I adapted
your example slightly to replace all of the lines
setting the signal handlers to one statement:

win32api.SetConsoleCtrlHandler (handler, 1)

and the handler function itself takes only one
arg, the signal no, and returns False to indicate
that control should pass to the next handler, which
will probably be the default Python handler:

def handler(arg):
print "Signal handler", arg
global workers
for w in workers:
w.stop()
return False
Hope that all helps.

TJG

Aug 9 '08 #1
0 1168

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

19 posts views Thread by Jane Austine | last post: by
3 posts views Thread by Peter Hansen | last post: by
5 posts views Thread by Francois De Serres | last post: by
2 posts views Thread by rbt | last post: by
5 posts views Thread by Lonewolf | last post: by
12 posts views Thread by Perecli Manole | last post: by
3 posts views Thread by =?Utf-8?B?Vmlua2k=?= | last post: by
6 posts views Thread by George Sakkis | last post: by
reply views Thread by suresh191 | last post: by
4 posts views Thread by guiromero | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.