|
Boost Users : |
Subject: Re: [Boost-users] [thread] await hangs when using boost::promise/future
From: Lee Clagett (forum_at_[hidden])
Date: 2015-01-18 01:14:30
On Sat, Jan 17, 2015 at 1:55 PM, Vicente J. Botet Escriba <
vicente.botet_at_[hidden]> wrote:
> Le 17/01/15 16:36, Vicente J. Botet Escriba a écrit :
>
> Le 17/01/15 15:36, Lee Clagett a écrit :
> The continuation then tries to acquire the mutex (has_exception), and
> blocks waiting for the set_value() to clear.
>
> The continuation is executed in another thread and only when it is
> ready (either there is a set_value or a set_exception). So the continuation
> shouldn't block.
>
> set_value() is in turn waiting for the continuation thread to join
> because nothing else has a handle to the thread.
>
> I don't understand how did you got this conclusion. Please could you
> clarify? I can understand that the as the blocking is on the shared future,
> the promise destructor will block in this case.
>
> This line here [
https://github.com/boostorg/thread/blob/master/include/boost/thread/future.hpp#L189
]. this_continuation_ptr is the last thing that references the continuation
thread, so it tries to join it during destruction, while the mutex is held
up the call stack. If the continuation thread calls a function on the
future it receives, it then must wait for the same mutex which will never
be released.
>
> The best way to get around this is to _not_ ignore the returned future
> from the .then call. I also have patch that fixes the second bug, but
> fixing the first bug will require enough changes that will likely result in
> an obsolete patch.
>
>
> Is the patch for Boost.Thread?
>
> Thanks for your comments. I will try to fix this the blocking issue asap
> but I suspect that this couldn't go into the next Boost version :(
>
> I have a patch here [
https://github.com/vtnerd/thread/compare/boostorg:develop...ContinuationFix
] that addresses the deadlock issue, and should allow the code by the OP to
work exactly as desired. However, the patch does not work as the docs
indicate. Instead of blocking on the destructor of the continuation future,
it will block in the destructor of the original future, OR the setter of
the original promise (which could be its destructor in broken_promise
case), whichever occurs last. Fixing the .then() blocking issue is a little
tricky because the destructor of the continuation future could need to wait
for a thread that won't be launched until a value is set in the original
promise.
Is blocking in the destructor of the continuation future necessary? A
callback signals when the original future has been set just the same. The
negative is the thread joining is a little more confusing to describe, and
deferred execution will not work correctly if the continuation future is
ignored (the test case in the patch above fails when the continuation
launch policy is deferred).
Lee
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net