LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 24692 - promise/future deadlock
Summary: promise/future deadlock
Status: CONFIRMED
Alias: None
Product: libc++
Classification: Unclassified
Component: All Bugs (show other bugs)
Version: unspecified
Hardware: All All
: P release blocker
Assignee: Eric Fiselier
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-09-03 09:03 PDT by Agustín Bergé
Modified: 2015-09-07 21:27 PDT (History)
3 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Agustín Bergé 2015-09-03 09:03:57 PDT
The following test case results in a deadlock:

    #include <chrono>
    #include <future>
    #include <iostream>
    #include <utility>

    template <typename T>
    struct weird {
      std::future<weird<T>> f;
  
      explicit weird(std::future<weird<T>> f) : f(std::move(f)) {}
  
      weird(weird&& other)
        : f(std::move(other.f))
      {
        if (f.wait_for(std::chrono::seconds(1)) == std::future_status::timeout) {
          std::cout << "Moving but the future is not ready yet\n";
        }
      }
    };

    int main() {
      std::promise<weird<int>> p;
      weird<int> w(p.get_future());
      p.set_value(std::move(w));
    }

This is caused by executing arbitrary user code under a lock.
Comment 1 Eric Fiselier 2015-09-04 18:11:18 PDT
Yikes... Thanks for the report.
Comment 2 Eric Fiselier 2015-09-04 18:49:21 PDT
@K-Ballo. Do you think that this code should actually work? It seems to me that this is likely non-standard.
Comment 3 Agustín Bergé 2015-09-07 06:53:36 PDT
(In reply to comment #2)
> @K-Ballo. Do you think that this code should actually work? It seems to me
> that this is likely non-standard.

Yes, I think this code is required to actually work. What makes you think this is non-standard?
Comment 4 Eric Fiselier 2015-09-07 21:27:02 PDT
I think the only possible way to fix this (without breaking the ABI) is to:

1. Release the lock while constructing the value.
2. Use the top bits of the `__state_` variable to implement a "construction lock" that will allow us to serialize multiple calls to "set_value(...)"

I'm not yet sure if this is going to work. I think it's likely that these changes aren't going to play nice with older versions of libc++.