Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #73918 > unrolled thread
| Started by | Ned Deily <nad@acm.org> |
|---|---|
| First post | 2014-07-03 13:13 -0700 |
| Last post | 2014-07-04 09:28 +1000 |
| Articles | 3 — 3 participants |
Back to article view | Back to comp.lang.python
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: threading.Condition.wait() is not catching SIGTERM Ned Deily <nad@acm.org> - 2014-07-03 13:13 -0700
Re: threading.Condition.wait() is not catching SIGTERM Roy Smith <roy@panix.com> - 2014-07-03 16:43 -0400
Re: threading.Condition.wait() is not catching SIGTERM Cameron Simpson <cs@zip.com.au> - 2014-07-04 09:28 +1000
| From | Ned Deily <nad@acm.org> |
|---|---|
| Date | 2014-07-03 13:13 -0700 |
| Subject | Re: threading.Condition.wait() is not catching SIGTERM |
| Message-ID | <mailman.11469.1404418450.18130.python-list@python.org> |
In article <17F05A1B-44C8-4F25-AFE9-5DBCFFB9982B@gmail.com>,
> I have the following code which when executed waits to be interrupted by
> SIGINT, SIGTERM or SIGQUIT. When an object is initialized, it creates a
> threading.Condition() and acquires() it! The program then registers the
> signal handlers where notify() and release() is called when the above
> mentioned signals are received. After registering the signal handlers, it
> calls wait() on the condition variable and block.
>
> When I tried to stop the program with Ctrl-C, its did not respond. IOW, the
> _signal_handler() method did not get called.
I'm not sure what you are trying to do but your test case seems flawed.
threading.Condition is designed to be used with multiple threads but
your test doesn't actually use threads. If you run your test with a
reasonably current Python 3 (after changing print to print()), you can
see that it fails (and why it fails) when interrupting with Ctrl-C:
Waiting to be interrupted!
^CReceived terminate request - signal = 2
Traceback (most recent call last):
File "b.py", line 30, in <module>
main()
File "b.py", line 27, in main
a.register_and_wait()
File "b.py", line 22, in register_and_wait
self._termination_signal.wait() # control blocks here!
File
"/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/threadin
g.py", line 289, in wait
waiter.acquire()
File "b.py", line 13, in _signal_handler
self._termination_signal.notify()
File
"/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/threadin
g.py", line 339, in notify
raise RuntimeError("cannot notify on un-acquired lock")
RuntimeError: cannot notify on un-acquired lock
After a quick glance, I'm not sure why Python 2.7 is behaving
differently, e.g. not raising an error, since both versions of
Condition.notify have the same test so the difference is elsewhere.
Feel free to open an issue for not catching the error in 2.7 but you
should rethink what you are trying to do here.
--
Ned Deily,
nad@acm.org
[toc] | [next] | [standalone]
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2014-07-03 16:43 -0400 |
| Message-ID | <roy-F18CDB.16431303072014@news.panix.com> |
| In reply to | #73918 |
In article <mailman.11469.1404418450.18130.python-list@python.org>,
Ned Deily <nad@acm.org> wrote:
> In article <17F05A1B-44C8-4F25-AFE9-5DBCFFB9982B@gmail.com>,
> > I have the following code which when executed waits to be interrupted by
> > SIGINT, SIGTERM or SIGQUIT. When an object is initialized, it creates a
> > threading.Condition() and acquires() it! The program then registers the
> > signal handlers where notify() and release() is called when the above
> > mentioned signals are received. After registering the signal handlers, it
> > calls wait() on the condition variable and block.
> >
> > When I tried to stop the program with Ctrl-C, its did not respond. IOW, the
> > _signal_handler() method did not get called.
>
> I'm not sure what you are trying to do but your test case seems flawed.
> threading.Condition is designed to be used with multiple threads but
> your test doesn't actually use threads. If you run your test with a
> reasonably current Python 3 (after changing print to print()), you can
> see that it fails (and why it fails) when interrupting with Ctrl-C:
>
> Waiting to be interrupted!
> ^CReceived terminate request - signal = 2
> Traceback (most recent call last):
> File "b.py", line 30, in <module>
> main()
> File "b.py", line 27, in main
> a.register_and_wait()
> File "b.py", line 22, in register_and_wait
> self._termination_signal.wait() # control blocks here!
> File
> "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/threadin
> g.py", line 289, in wait
> waiter.acquire()
> File "b.py", line 13, in _signal_handler
> self._termination_signal.notify()
> File
> "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/threadin
> g.py", line 339, in notify
> raise RuntimeError("cannot notify on un-acquired lock")
> RuntimeError: cannot notify on un-acquired lock
>
> After a quick glance, I'm not sure why Python 2.7 is behaving
> differently, e.g. not raising an error, since both versions of
> Condition.notify have the same test so the difference is elsewhere.
> Feel free to open an issue for not catching the error in 2.7 but you
> should rethink what you are trying to do here.
That's not the whole story. I was playing around with his example this
morning (Python 2.7.1, OSX, Darwin Kernel Version 11.4.2). My original
thought was that maybe the wait() call is holding the GIL and breaking
it up into two threads would solve that somehow. So, I tried this:
---------------------------------
from signal import signal, SIGINT, SIGTERM, SIGQUIT
from threading import Condition, Thread, current_thread
import time
class A:
def __init__(self):
self._termination_signal = Condition()
def _signal_handler(self, signum, frame):
print "Received terminate request - signal = {0}".format(signum,)
del frame
return
def register_and_wait(self):
t = Thread(target=A.run, args=[self._termination_signal])
t.start()
signal(SIGINT, self._signal_handler)
signal(SIGTERM, self._signal_handler)
signal(SIGQUIT, self._signal_handler)
@staticmethod
def run(ts):
ts.acquire(blocking=0)
print "Waiting to be interrupted!"
ts.wait() # control blocks here!
print "Notified!!"
def main():
a = A()
a.register_and_wait()
if __name__ == "__main__":
main()
---------------------------------------
I got the same result: _signal_handler() never gets called. You may be
right that at the point where notify() gets called, you don't have a
lock, but that's moot because you never even get to that point. That's
the fundamental problem here, and it sure smells like a deadlock. And
since it happens even in the non-threaded version, my nose says it's
somehow GIL related.
I just noticed that the acquire call is documented as taking
specifically True or False, not generically something truthy or falsey.
I tried it again with accept(blocking=False) and got the same result.
Hmmm, I just also noticed what I think is a bug in the docs
(https://docs.python.org/2/library/threading.html). It says, "If a call
with blocking set to True would block, return False immediately". Isn't
that backwards? Doesn't that describe the blocking=False behavior?
[toc] | [prev] | [next] | [standalone]
| From | Cameron Simpson <cs@zip.com.au> |
|---|---|
| Date | 2014-07-04 09:28 +1000 |
| Message-ID | <mailman.11475.1404431213.18130.python-list@python.org> |
| In reply to | #73920 |
On 03Jul2014 16:43, Roy Smith <roy@panix.com> wrote: [...] >Hmmm, I just also noticed what I think is a bug in the docs >(https://docs.python.org/2/library/threading.html). It says, "If a call >with blocking set to True would block, return False immediately". Isn't >that backwards? Doesn't that describe the blocking=False behavior? If you mean this text under Lock.acquire: When invoked with the blocking argument set to False, do not block. If a call with blocking set to True would block, return False immediately; otherwise, set the lock to locked and return True. that pretty clearly (to me) describes blocking=False, by contrasting it with a behaviour that would obtain if blocking=True. It is in the clause describing "the blocking argument set to False", after all. Cheers, Cameron Simpson <cs@zip.com.au>
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web