diff mbox

PR libstdc++/80316 make promise::set_value throw no_state error

Message ID 20170712101546.GP15340@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely July 12, 2017, 10:15 a.m. UTC
On 12/07/17 09:46 +0200, Christophe Lyon wrote:
>On 11 July 2017 at 14:39, Jonathan Wakely <jwakely@redhat.com> wrote:
>> On 11/07/17 12:53 +0100, Jonathan Wakely wrote:
>>>
>>> On 21/04/17 15:54 +0100, Jonathan Wakely wrote:
>>>>
>>>> On 4 April 2017 at 20:44, Jonathan Wakely wrote:
>>>>>
>>>>> We got a bug report from a customer pointing out that calling
>>>>> promise::set_value on a moved-from promise crashes instead of throwing
>>>>> an exception with error code future_errc::no_state.
>>>>>
>>>>> This fixes it, by moving the _S_check calls to *before* we deference
>>>>> the pointer that the calls check!
>>>>>
>>>>> This passes all tests, including the more comprehensive ones I've
>>>>> added as part of this commit, but I think it can wait for stage 1
>>>>> anyway. We've been shipping this bug for a couple of releases already.
>>>>>
>>>>>        PR libstdc++/80316
>>>>>        * include/std/future (_State_baseV2::_Setter::operator()): Remove
>>>>>        _S_check calls that are done after the pointer to the shared
>>>>> state
>>>>> is
>>>>>        already dereferenced.
>>>>>        (_State_baseV2::_Setter<_Res, void>): Define specialization for
>>>>> void
>>>>>        as partial specialization so it can be defined within the
>>>>> definition
>>>>>        of _State_baseV2.
>>>>>        (_State_baseV2::__setter): Call _S_check.
>>>>>        (_State_baseV2::__setter(promise<void>*)): Add overload for use
>>>>> by
>>>>>        promise<void>::set_value and
>>>>> promise<void>::set_value_at_thread_exit.
>>>>>        (promise<T>, promise<T&>, promise<void>): Make _State a friend.
>>>>>        (_State_baseV2::_Setter<void, void>): Remove explicit
>>>>> specialization.
>>>>>        (promise<void>::set_value,
>>>>> promise<void>::set_value_at_thread_exit):
>>>>>        Use new __setter overload.
>>>>>        * testsuite/30_threads/promise/members/at_thread_exit2.cc: New
>>>>> test.
>>>>>        * testsuite/30_threads/promise/members/set_exception.cc: Test
>>>>>        promise<T&> and promise<void> specializations.
>>>>>        * testsuite/30_threads/promise/members/set_exception2.cc:
>>>>> Likewise.
>>>>>        Test for no_state error condition.
>>>>>        * testsuite/30_threads/promise/members/set_value2.cc: Likewise.
>>>>
>>>>
>>>>
>>>> This is now committed to trunk.
>>>
>>>
>>> And now also to gcc-7-branch.
>>
>>
>> And gcc-6-branch.
>>
>
>Hi Jonathan,
>
>The new test fails to compile on arm when forcing -march=armv5t:
>/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:
>In function 'void test01()':^M
>/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:31:
>error: aggregate 'std::promise<int> p1' has incomplete type and cannot
>be defined^M
>/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:44:
>error: 'make_exception_ptr' is not a member of 'std'^M
>/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:52:
>error: variable 'std::promise<int> p2' has initializer but incomplete
>type^M
>/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:64:
>error: 'make_exception_ptr' is not a member of 'std'^M
>/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:
>In function 'void test02()':^M
>/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:75:
>error: aggregate 'std::promise<int&> p1' has incomplete type and
>cannot be defined^M
>/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:89:
>error: 'make_exception_ptr' is not a member of 'std'^M
>/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:97:
>error: variable 'std::promise<int&> p2' has initializer but incomplete
>type^M
>/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:110:
>error: 'make_exception_ptr' is not a member of 'std'^M
>/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:
>In function 'void test03()':^M
>/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:121:
>error: aggregate 'std::promise<void> p1' has incomplete type and
>cannot be defined^M
>/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:134:
>error: 'make_exception_ptr' is not a member of 'std'^M
>/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:142:
>error: variable 'std::promise<void> p2' has initializer but incomplete
>type^M
>/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:153:
>error: 'make_exception_ptr' is not a member of 'std'^M
>compiler exited with status 1
>
>I can see this on target arm-none-linux-gnueabihf --with-mode arm
>--with-cpu cortex-a9 --with-fpu vfp and setting -march=armv5t in
>runtestflags.
>
>It also looks like you forgot to add a ChangeLog entry for the
>testsuite changes.

These changes?

	* testsuite/30_threads/promise/members/at_thread_exit2.cc: New test.
	* testsuite/30_threads/promise/members/set_exception.cc: Test
	promise<T&> and promise<void> specializations.
	* testsuite/30_threads/promise/members/set_exception2.cc: Likewise.
	Test for no_state error condition.
	* testsuite/30_threads/promise/members/set_value2.cc: Likewise.


>There is no such error on the gcc-7 branch.

Because armv5 supports <future> on that branch.

This should fix it, committed to gcc-6-branch.

Comments

Christophe Lyon July 12, 2017, 2:49 p.m. UTC | #1
On 12 July 2017 at 12:15, Jonathan Wakely <jwakely@redhat.com> wrote:
> On 12/07/17 09:46 +0200, Christophe Lyon wrote:
>>
>> On 11 July 2017 at 14:39, Jonathan Wakely <jwakely@redhat.com> wrote:
>>>
>>> On 11/07/17 12:53 +0100, Jonathan Wakely wrote:
>>>>
>>>>
>>>> On 21/04/17 15:54 +0100, Jonathan Wakely wrote:
>>>>>
>>>>>
>>>>> On 4 April 2017 at 20:44, Jonathan Wakely wrote:
>>>>>>
>>>>>>
>>>>>> We got a bug report from a customer pointing out that calling
>>>>>> promise::set_value on a moved-from promise crashes instead of throwing
>>>>>> an exception with error code future_errc::no_state.
>>>>>>
>>>>>> This fixes it, by moving the _S_check calls to *before* we deference
>>>>>> the pointer that the calls check!
>>>>>>
>>>>>> This passes all tests, including the more comprehensive ones I've
>>>>>> added as part of this commit, but I think it can wait for stage 1
>>>>>> anyway. We've been shipping this bug for a couple of releases already.
>>>>>>
>>>>>>        PR libstdc++/80316
>>>>>>        * include/std/future (_State_baseV2::_Setter::operator()):
>>>>>> Remove
>>>>>>        _S_check calls that are done after the pointer to the shared
>>>>>> state
>>>>>> is
>>>>>>        already dereferenced.
>>>>>>        (_State_baseV2::_Setter<_Res, void>): Define specialization for
>>>>>> void
>>>>>>        as partial specialization so it can be defined within the
>>>>>> definition
>>>>>>        of _State_baseV2.
>>>>>>        (_State_baseV2::__setter): Call _S_check.
>>>>>>        (_State_baseV2::__setter(promise<void>*)): Add overload for use
>>>>>> by
>>>>>>        promise<void>::set_value and
>>>>>> promise<void>::set_value_at_thread_exit.
>>>>>>        (promise<T>, promise<T&>, promise<void>): Make _State a friend.
>>>>>>        (_State_baseV2::_Setter<void, void>): Remove explicit
>>>>>> specialization.
>>>>>>        (promise<void>::set_value,
>>>>>> promise<void>::set_value_at_thread_exit):
>>>>>>        Use new __setter overload.
>>>>>>        * testsuite/30_threads/promise/members/at_thread_exit2.cc: New
>>>>>> test.
>>>>>>        * testsuite/30_threads/promise/members/set_exception.cc: Test
>>>>>>        promise<T&> and promise<void> specializations.
>>>>>>        * testsuite/30_threads/promise/members/set_exception2.cc:
>>>>>> Likewise.
>>>>>>        Test for no_state error condition.
>>>>>>        * testsuite/30_threads/promise/members/set_value2.cc: Likewise.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> This is now committed to trunk.
>>>>
>>>>
>>>>
>>>> And now also to gcc-7-branch.
>>>
>>>
>>>
>>> And gcc-6-branch.
>>>
>>
>> Hi Jonathan,
>>
>> The new test fails to compile on arm when forcing -march=armv5t:
>>
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:
>> In function 'void test01()':^M
>>
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:31:
>> error: aggregate 'std::promise<int> p1' has incomplete type and cannot
>> be defined^M
>>
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:44:
>> error: 'make_exception_ptr' is not a member of 'std'^M
>>
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:52:
>> error: variable 'std::promise<int> p2' has initializer but incomplete
>> type^M
>>
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:64:
>> error: 'make_exception_ptr' is not a member of 'std'^M
>>
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:
>> In function 'void test02()':^M
>>
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:75:
>> error: aggregate 'std::promise<int&> p1' has incomplete type and
>> cannot be defined^M
>>
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:89:
>> error: 'make_exception_ptr' is not a member of 'std'^M
>>
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:97:
>> error: variable 'std::promise<int&> p2' has initializer but incomplete
>> type^M
>>
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:110:
>> error: 'make_exception_ptr' is not a member of 'std'^M
>>
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:
>> In function 'void test03()':^M
>>
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:121:
>> error: aggregate 'std::promise<void> p1' has incomplete type and
>> cannot be defined^M
>>
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:134:
>> error: 'make_exception_ptr' is not a member of 'std'^M
>>
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:142:
>> error: variable 'std::promise<void> p2' has initializer but incomplete
>> type^M
>>
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc:153:
>> error: 'make_exception_ptr' is not a member of 'std'^M
>> compiler exited with status 1
>>
>> I can see this on target arm-none-linux-gnueabihf --with-mode arm
>> --with-cpu cortex-a9 --with-fpu vfp and setting -march=armv5t in
>> runtestflags.
>>
>> It also looks like you forgot to add a ChangeLog entry for the
>> testsuite changes.
>
>
> These changes?

Yes

>
>         * testsuite/30_threads/promise/members/at_thread_exit2.cc: New test.
>         * testsuite/30_threads/promise/members/set_exception.cc: Test
>         promise<T&> and promise<void> specializations.
>         * testsuite/30_threads/promise/members/set_exception2.cc: Likewise.
>         Test for no_state error condition.
>         * testsuite/30_threads/promise/members/set_value2.cc: Likewise.
>
>
>> There is no such error on the gcc-7 branch.
>
>
> Because armv5 supports <future> on that branch.
>
> This should fix it, committed to gcc-6-branch.
>
I confirm it's now OK.

Thanks
diff mbox

Patch

commit b30c811b2a0ac1497552e153324dd25a65ffa5a7
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Jul 12 11:02:11 2017 +0100

    Only run new test on targets that support std::promise
    
    	* testsuite/30_threads/promise/members/at_thread_exit2.cc: Require
    	atomic builtins.

diff --git a/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc b/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc
index 9429a99..a9b0882 100644
--- a/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc
+++ b/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit2.cc
@@ -3,6 +3,7 @@ 
 // { dg-require-effective-target c++11 }
 // { dg-require-cstdint "" }
 // { dg-require-gthreads "" }
+// { dg-require-atomic-builtins "" }
 
 // Copyright (C) 2014-2017 Free Software Foundation, Inc.
 //