public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libstdc++/103382] New: condition_variable::wait() is not cancellable because it is marked noexcept
@ 2021-11-23 13:01 vanyacpp at gmail dot com
  2021-11-23 13:06 ` [Bug libstdc++/103382] " vanyacpp at gmail dot com
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: vanyacpp at gmail dot com @ 2021-11-23 13:01 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103382

            Bug ID: 103382
           Summary: condition_variable::wait() is not cancellable because
                    it is marked noexcept
           Product: gcc
           Version: 10.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: vanyacpp at gmail dot com
  Target Milestone: ---

At the moment condition_variable::wait() is marked noexcept. It means that if
pthread_cond_wait() acts as cancellation point and throws an exception the
program is terminated with std::terminate(). This program demonstrates the
issue:

#include <condition_variable>
#include <thread>

int main()
{
    std::mutex m;
    std::condition_variable cv;

    std::thread th([&]
    {
        std::unique_lock lock(m);
        cv.wait(lock);
    });

    pthread_cancel(th.native_handle());
    th.join();
}

This program terminates with SIGABRT.

Because of this using condition_variable::wait() in cancellable threads is
tricky: the programmer has to guard all calls to condition_variable::wait()
with disabling/restoring cancellation state. Also this stops the thread from
being cancellable while in wait(). Therefore the outer thread has to know which
condition_variable the thread waits and notify this condition_variable after
pthread_cancel(). Also one should add cancellation point pthread_testcancel()
immediately after restoring cancellation state after wait().

I believe it would be great if condition_variable::wait interacted nicer with
POSIX-cancellation. I would like to suggest removing noexcept from
condition_variable::wait(). This also matches the C++ standard very well
[thread.condition.condvar] where condition_variable::wait() is not marked as
noexcept.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug libstdc++/103382] condition_variable::wait() is not cancellable because it is marked noexcept
  2021-11-23 13:01 [Bug libstdc++/103382] New: condition_variable::wait() is not cancellable because it is marked noexcept vanyacpp at gmail dot com
@ 2021-11-23 13:06 ` vanyacpp at gmail dot com
  2021-11-23 13:44 ` redi at gcc dot gnu.org
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: vanyacpp at gmail dot com @ 2021-11-23 13:06 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103382

--- Comment #1 from Ivan Sorokin <vanyacpp at gmail dot com> ---
Please note there was a related issue PR67726. I hope it is possible to meet
the requirements mentioned in the issue as well as enabling cancellation.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug libstdc++/103382] condition_variable::wait() is not cancellable because it is marked noexcept
  2021-11-23 13:01 [Bug libstdc++/103382] New: condition_variable::wait() is not cancellable because it is marked noexcept vanyacpp at gmail dot com
  2021-11-23 13:06 ` [Bug libstdc++/103382] " vanyacpp at gmail dot com
@ 2021-11-23 13:44 ` redi at gcc dot gnu.org
  2021-11-24 14:46 ` vanyacpp at gmail dot com
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: redi at gcc dot gnu.org @ 2021-11-23 13:44 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103382

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2021-11-23
     Ever confirmed|0                           |1

--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Ivan Sorokin from comment #0)
> This also matches the C++ standard very well
> [thread.condition.condvar] where condition_variable::wait() is not marked as
> noexcept.

Huh, I thought it was noexcept. Then yes, we should remove it.

There are still lots of other places where the stadnard does require 'noexcept'
and cancellation will terminate. NPTL thread cancellation via __forced_unwind
just doesn't work well in C++.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug libstdc++/103382] condition_variable::wait() is not cancellable because it is marked noexcept
  2021-11-23 13:01 [Bug libstdc++/103382] New: condition_variable::wait() is not cancellable because it is marked noexcept vanyacpp at gmail dot com
  2021-11-23 13:06 ` [Bug libstdc++/103382] " vanyacpp at gmail dot com
  2021-11-23 13:44 ` redi at gcc dot gnu.org
@ 2021-11-24 14:46 ` vanyacpp at gmail dot com
  2021-11-24 22:10 ` redi at gcc dot gnu.org
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: vanyacpp at gmail dot com @ 2021-11-24 14:46 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103382

--- Comment #3 from Ivan Sorokin <vanyacpp at gmail dot com> ---
> Huh, I thought it was noexcept. Then yes, we should remove it.

Thank you very much! I'm looking forward for a fix.

> There are still lots of other places where the stadnard does require 'noexcept' and cancellation will terminate.

Do you have any specific functions in mind? If so perhaps something can be done
about them too.

Some people claim that noexcept and cancellation and mutually incompatible, but
I don't think this is the case. I believe that by following a simple discipline
noexcept and cancellation can interact very well.

First of all not all noexcept functions are problematic: noexcept functions
that don't call cancellation points are perfectly fine.

The noexcept functions that do call some cancellation points can be fixed by
suppression/restoring of cancellation. For example, a destructor that calls
close() which is a cancellation point should just suppress/restore
cancellation. Same for a destructor that calls pthread_join(). One might say
that because of this we lose some cancellation points and this is true, but I
believe that noexcept are the places where program can not recover preserving
exception guarantees and having cancellation suppressed in these places is
perfectly fine.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug libstdc++/103382] condition_variable::wait() is not cancellable because it is marked noexcept
  2021-11-23 13:01 [Bug libstdc++/103382] New: condition_variable::wait() is not cancellable because it is marked noexcept vanyacpp at gmail dot com
                   ` (2 preceding siblings ...)
  2021-11-24 14:46 ` vanyacpp at gmail dot com
@ 2021-11-24 22:10 ` redi at gcc dot gnu.org
  2021-12-09 23:27 ` cvs-commit at gcc dot gnu.org
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: redi at gcc dot gnu.org @ 2021-11-24 22:10 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103382

--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Yes, it's just a lot of work to implement correctly, and non-zero overhead to
change the cancellation state.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug libstdc++/103382] condition_variable::wait() is not cancellable because it is marked noexcept
  2021-11-23 13:01 [Bug libstdc++/103382] New: condition_variable::wait() is not cancellable because it is marked noexcept vanyacpp at gmail dot com
                   ` (3 preceding siblings ...)
  2021-11-24 22:10 ` redi at gcc dot gnu.org
@ 2021-12-09 23:27 ` cvs-commit at gcc dot gnu.org
  2021-12-09 23:38 ` redi at gcc dot gnu.org
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2021-12-09 23:27 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103382

--- Comment #5 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:9e18a25331fa25c3907249fede65a02c6817b06e

commit r12-5877-g9e18a25331fa25c3907249fede65a02c6817b06e
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Dec 7 15:11:15 2021 +0000

    libstdc++: Allow std::condition_variable waits to be cancelled [PR103382]

    std::condition_variable::wait(unique_lock<mutex>&) is incorrectly marked
    noexcept, which means that the __forced_unwind exception used by NPTL
    cancellation will terminate the process. It should allow exceptions to
    pass through, so that a thread can be cleanly cancelled when waiting on
    a condition variable.

    The new behaviour is exported as a new version of the symbol, to avoid
    an ABI break for existing code linked to the non-throwing definition of
    the function. Code linked against older releases will have a reference
    to the @GLIBCXX_3.4.11 version, andcode compiled against the new
    libstdc++ will get a reference to the @@GLIBCXX_3.4.30 version.

    libstdc++-v3/ChangeLog:

            PR libstdc++/103382
            * config/abi/pre/gnu.ver (GLIBCXX_3.4.11): Do not export old
            symbol if .symver renaming is supported.
            (GLIBCXX_3.4.30): Export new symbol if .symver renaming is
            supported.
            * doc/xml/manual/evolution.xml: Document change.
            * doc/html/manual/api.html: Regenerate.
            * include/bits/std_mutex.h (__condvar::wait,
__condvar::wait_until):
            Remove noexcept.
            * include/std/condition_variable (condition_variable::wait):
            Likewise.
            * src/c++11/condition_variable.cc (condition_variable::wait):
            Likewise.
            * src/c++11/compatibility-condvar.cc (__nothrow_wait_cv::wait):
            Define nothrow wrapper around std::condition_variable::wait and
            export the old symbol as an alias to it.
            * testsuite/30_threads/condition_variable/members/103382.cc: New
test.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug libstdc++/103382] condition_variable::wait() is not cancellable because it is marked noexcept
  2021-11-23 13:01 [Bug libstdc++/103382] New: condition_variable::wait() is not cancellable because it is marked noexcept vanyacpp at gmail dot com
                   ` (4 preceding siblings ...)
  2021-12-09 23:27 ` cvs-commit at gcc dot gnu.org
@ 2021-12-09 23:38 ` redi at gcc dot gnu.org
  2022-09-06 12:35 ` vanyacpp at gmail dot com
  2022-09-06 12:53 ` redi at gcc dot gnu.org
  7 siblings, 0 replies; 9+ messages in thread
From: redi at gcc dot gnu.org @ 2021-12-09 23:38 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103382

--- Comment #6 from Jonathan Wakely <redi at gcc dot gnu.org> ---
The incorrect noexcept is fixed for GCC 12, but isn't suitable to backport.

For the branches we should consider disabling cancellation as suggested in
https://gcc.gnu.org/pipermail/gcc-patches/2021-December/586406.html

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug libstdc++/103382] condition_variable::wait() is not cancellable because it is marked noexcept
  2021-11-23 13:01 [Bug libstdc++/103382] New: condition_variable::wait() is not cancellable because it is marked noexcept vanyacpp at gmail dot com
                   ` (5 preceding siblings ...)
  2021-12-09 23:38 ` redi at gcc dot gnu.org
@ 2022-09-06 12:35 ` vanyacpp at gmail dot com
  2022-09-06 12:53 ` redi at gcc dot gnu.org
  7 siblings, 0 replies; 9+ messages in thread
From: vanyacpp at gmail dot com @ 2022-09-06 12:35 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103382

Ivan Sorokin <vanyacpp at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |FIXED

--- Comment #7 from Ivan Sorokin <vanyacpp at gmail dot com> ---
As the bug is fixed I'm closing the issue.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug libstdc++/103382] condition_variable::wait() is not cancellable because it is marked noexcept
  2021-11-23 13:01 [Bug libstdc++/103382] New: condition_variable::wait() is not cancellable because it is marked noexcept vanyacpp at gmail dot com
                   ` (6 preceding siblings ...)
  2022-09-06 12:35 ` vanyacpp at gmail dot com
@ 2022-09-06 12:53 ` redi at gcc dot gnu.org
  7 siblings, 0 replies; 9+ messages in thread
From: redi at gcc dot gnu.org @ 2022-09-06 12:53 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103382

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Assignee|unassigned at gcc dot gnu.org      |redi at gcc dot gnu.org
         Resolution|FIXED                       |---
             Status|RESOLVED                    |ASSIGNED

--- Comment #8 from Jonathan Wakely <redi at gcc dot gnu.org> ---
As I said in comment 6, we might want to disable cancellation in the release
branches.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-09-06 12:53 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-23 13:01 [Bug libstdc++/103382] New: condition_variable::wait() is not cancellable because it is marked noexcept vanyacpp at gmail dot com
2021-11-23 13:06 ` [Bug libstdc++/103382] " vanyacpp at gmail dot com
2021-11-23 13:44 ` redi at gcc dot gnu.org
2021-11-24 14:46 ` vanyacpp at gmail dot com
2021-11-24 22:10 ` redi at gcc dot gnu.org
2021-12-09 23:27 ` cvs-commit at gcc dot gnu.org
2021-12-09 23:38 ` redi at gcc dot gnu.org
2022-09-06 12:35 ` vanyacpp at gmail dot com
2022-09-06 12:53 ` redi at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).