Bug 68921 - [5/6 Regression] std::future::wait() makes invalid futex calls and spins
Summary: [5/6 Regression] std::future::wait() makes invalid futex calls and spins
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 5.3.1
: P3 normal
Target Milestone: 5.4
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-12-15 18:02 UTC by Jonathan Wakely
Modified: 2015-12-16 11:50 UTC (History)
2 users (show)

See Also:
Host:
Target: i?86-*linux*
Build:
Known to work: 4.9.3
Known to fail:
Last reconfirmed: 2015-12-15 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Wakely 2015-12-15 18:02:57 UTC
On 32-bit linux the following spins in a tight loop until it times out:

#include <future>
#include <thread>

int main() {
  std::promise<void> p;
  auto f = p.get_future();

  std::thread t([&p](){
    std::this_thread::sleep_for(std::chrono::seconds(10));
    p.set_value();
  });

  f.wait();

  t.join();
}

strace shows thousands of invalid calls:

futex(0x8cf2a24, FUTEX_WAIT, 2147483648, {4289120584, 134527555}) = -1 EINVAL (Invalid argument)

It's called from the infinite loop in __atomic_futex_unsigned::_M_load_and_test_until in <bits/atomic_futex.h>
Comment 1 Jonathan Wakely 2015-12-15 18:29:32 UTC
This fixes it:

--- a/libstdc++-v3/src/c++11/futex.cc
+++ b/libstdc++-v3/src/c++11/futex.cc
@@ -52,7 +52,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        // we will fall back to spin-waiting.  The only thing we could do
        // here on errors is abort.
        int ret __attribute__((unused));
-       ret = syscall (SYS_futex, __addr, futex_wait_op, __val);
+       ret = syscall (SYS_futex, __addr, futex_wait_op, __val, nullptr);
        _GLIBCXX_DEBUG_ASSERT(ret == 0 || errno == EINTR || errno == EAGAIN);
        return true;
       }
Comment 2 Carlos O'Donell 2015-12-15 19:32:05 UTC
(In reply to Jonathan Wakely from comment #1)
> This fixes it:
> 
> --- a/libstdc++-v3/src/c++11/futex.cc
> +++ b/libstdc++-v3/src/c++11/futex.cc
> @@ -52,7 +52,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>         // we will fall back to spin-waiting.  The only thing we could do
>         // here on errors is abort.
>         int ret __attribute__((unused));
> -       ret = syscall (SYS_futex, __addr, futex_wait_op, __val);
> +       ret = syscall (SYS_futex, __addr, futex_wait_op, __val, nullptr);
>         _GLIBCXX_DEBUG_ASSERT(ret == 0 || errno == EINTR || errno == EAGAIN);
>         return true;
>        }

That is correct.

futex.2 from draft_futex upstream branch of linux man pages project:
~~~
If  the timeout argument is non-NULL, its contents specify a relative timeout
for the wait, measured according to the CLOCK_MONOTONIC clock.  (This  inter‐
val will be rounded up to the system clock granularity, and is guaranteed not
to expire early.)  If timeout is NULL, the call blocks indefinitely.
~~~

I assume you want to block indefinitely.
Comment 3 torvald 2015-12-15 20:03:30 UTC
LGTM, thanks.  Would be nice to backport this.
Comment 4 Jonathan Wakely 2015-12-16 10:40:36 UTC
Author: redi
Date: Wed Dec 16 10:40:04 2015
New Revision: 231676

URL: https://gcc.gnu.org/viewcvs?rev=231676&root=gcc&view=rev
Log:
libstdc++/68921 add timeout argument to futex(2)

	PR libstdc++/68921
	* src/c++11/futex.cc
	(__atomic_futex_unsigned_base::_M_futex_wait_until): Use null pointer
	as timeout argument.

Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/src/c++11/futex.cc
Comment 5 Jonathan Wakely 2015-12-16 11:49:27 UTC
Author: redi
Date: Wed Dec 16 11:48:55 2015
New Revision: 231679

URL: https://gcc.gnu.org/viewcvs?rev=231679&root=gcc&view=rev
Log:
libstdc++/68921 add timeout argument to futex(2)

	PR libstdc++/68921
	* src/c++11/futex.cc
	(__atomic_futex_unsigned_base::_M_futex_wait_until): Use null pointer
	as timeout argument.

Modified:
    branches/gcc-5-branch/libstdc++-v3/ChangeLog
    branches/gcc-5-branch/libstdc++-v3/src/c++11/futex.cc
Comment 6 Jonathan Wakely 2015-12-16 11:50:03 UTC
Fixed for 5.4