Opened 8 years ago
Closed 5 years ago
#10964 closed Bugs (fixed)
future<future<T>>::unwrap().then() Deadlocks
Reported by: | Owned by: | viboes | |
---|---|---|---|
Milestone: | To Be Determined | Component: | thread |
Version: | Boost 1.57.0 | Severity: | Problem |
Keywords: | Cc: | contact@… |
Description
The shared_state returned by unwrap() doesn't appear to propagate continuation information properly. The following code will deadlock, but the continuations should be immediately invoked.
struct TestCallback { typedef boost::future<void> result_type; result_type operator()(boost::future<void> future) const { future.get(); return boost::make_ready_future(); } result_type operator()(boost::future<boost::future<void>> future) const { future.get(); return boost::make_ready_future(); } }; int main() { boost::make_ready_future().then( TestCallback()).unwrap().then(TestCallback()).get(); return 0; }
Change History (22)
comment:1 by , 8 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:2 by , 8 years ago
Milestone: | To Be Determined → Boost 1.58.0 |
---|
comment:3 by , 8 years ago
The following doesn't work after the patch
boost::async(f).then( TestCallback()).unwrap().then(TestCallback()).get();
comment:4 by , 8 years ago
This commit should fix it
https://github.com/boostorg/thread/commit/45510facc743aa348e501642ce3d607d12dc7cfc
comment:5 by , 8 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
comment:6 by , 7 years ago
Milestone: | Boost 1.58.0 → To Be Determined |
---|---|
Resolution: | fixed |
Status: | closed → reopened |
The problem is yet there
and
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::lock_error> >' what(): boost: mutex lock failed in pthread_mutex_lock: Resource deadlock avoided
comment:7 by , 7 years ago
Status: | reopened → new |
---|
comment:8 by , 7 years ago
Status: | new → assigned |
---|
comment:10 by , 7 years ago
Yes, please. Any help will be welcome, an hint, a trace back, requesting for something you don't understand and find weird.
It would be great if you test with the branch https://github.com/boostorg/thread/tree/feature/make_executors_copyable, which make use of non-blocking futures also.
BTW, what is your name?
comment:11 by , 7 years ago
Lee Clagett. I've discussed Futures with you on the mailing list before. Unfortunately my name is after the @ in my email, so it doesn't show here, didn't think about that.
comment:13 by , 7 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
It seems that https://github.com/boostorg/thread/commit/60a8cb9b5c69423ee0bea403cacc971606575f01 fixes it.
I don't see anymore the errors.
comment:14 by , 7 years ago
I noticed that too. Looks like this is going to be a fun one.
I tried to recreate this issue on OSX (closest to FreeBSD I had), but no luck. And Clang's tsan isn't supported on OSX, at least on my version. I now have a FreeBSD VM, but I just found out that tsan isn't supported on this platform either! I'll run the tests on this system anyway, before moving to one my Linux systems with tsan. After that its begging Flast to do some investigating for me with some code auditing on the side.
comment:15 by , 7 years ago
Oh, and is it possible that he had a bad build? I feel like that may have happened on one of his systems, I'll try to ask him that ASAP.
comment:16 by , 5 years ago
I’ve encountered a similar problem while using deferred continuations (see https://stackoverflow.com/questions/44748568/boostfuture-deferred-continuation-unwrapping-deadlocks).
#define BOOST_THREAD_VERSION 5 #include <iostream> #include <boost/thread/future.hpp> int main(int argc, char* argv[]) { boost::promise<int> promise; boost::future<int> future = promise.get_future(); promise.set_value(42); int result = future.then( boost::launch::deferred, [](boost::future<int> result) { return boost::make_ready_future(result.get()); } ).unwrap().get(); std::cout << "Result is: " << result << std::endl; return 0; }
This code causes a deadlock. If the launch policy is replaced by boost::launch::async
, it works as intended.
comment:17 by , 5 years ago
Resolution: | fixed |
---|---|
Status: | closed → reopened |
comment:18 by , 5 years ago
Cc: | added |
---|
comment:19 by , 5 years ago
@Matteo Please, create a new issue, as the case you are describing is different than the original one.
comment:20 by , 5 years ago
See "VS 2017.4 Preview deadlocks on Test 10964" https://github.com/boostorg/thread/issues/132
comment:21 by , 5 years ago
Matteo, could you try with
#define BOOST_THREAD_VERSION 4
Version 5 has not been delivered officially.
The main difference of version 5 would be that BOOST_THREAD_ASYNC_FUTURE_WAITS is not defined (BOOST_THREAD_FUTURE_BLOCKING neither).
~future_async_shared_state_base() { #ifdef BOOST_THREAD_FUTURE_BLOCKING join(); #elif defined BOOST_THREAD_ASYNC_FUTURE_WAITS unique_lock<boost::mutex> lk(this->mutex); while(!this->done) { this->waiters.wait(lk); } #endif }
but I have no tested it too much. It seems that there are some big implications.
comment:22 by , 5 years ago
Resolution: | → fixed |
---|---|
Status: | reopened → closed |
https://github.com/boostorg/thread/commit/c16ec42941a92210033bddee3ef4eb42fd2b1a03