This is the mail archive of the
mailing list for the GCC project.
Re: Behaviour of __forced_unwind with noexcept
- From: Richard Biener <richard dot guenther at gmail dot com>
- To: Jonathan Wakely <jwakely dot gcc at gmail dot com>
- Cc: Ron <ron at bitbabbler dot org>, "gcc at gcc dot gnu dot org" <gcc at gcc dot gnu dot org>
- Date: Tue, 15 Aug 2017 13:31:10 +0200
- Subject: Re: Behaviour of __forced_unwind with noexcept
- Authentication-results: sourceware.org; auth=none
- References: <20170813182002.GJ12030@hex.shelbyville.oz> <CAH6eHdRgU6GVYJ5WD4480JJ_qOD1oYzN4UC+4SDirFdp8yj=1Q@mail.gmail.com> <20170815044413.GT12030@hex.shelbyville.oz> <CAFiYyc0iaN082icVjeT4bdGv4OYbVFBnpX+LX7Ncc7Mt=znnAQ@mail.gmail.com> <CAH6eHdQV3ooZRgi6i+Zh=WvYrKOSrcGA-E3F+mxvef7nWemail@example.com>
On Tue, Aug 15, 2017 at 1:28 PM, Jonathan Wakely <firstname.lastname@example.org> wrote:
> On 15 August 2017 at 11:24, Richard Biener <email@example.com> wrote:
>> On Tue, Aug 15, 2017 at 6:44 AM, Ron <firstname.lastname@example.org> wrote:
>>> On Mon, Aug 14, 2017 at 06:22:39PM +0100, Jonathan Wakely wrote:
>>>> On 13 August 2017 at 19:20, Ron wrote:
>>>> > Hi,
>>>> > I'm looking for some clarification of how the __forced_unwind thread
>>>> > cancellation exceptions intersect with noexcept. I've long been a
>>>> > big fan of the __forced_unwind idiom, but now that C++14 is the default
>>>> > since GCC 6.1, and many methods including destructors are implicitly
>>>> > noexcept, using it safely appears to have become a lot more tricky.
>>>> > The closest I've found so far to an "authoritative" statement of the
>>>> > expected behaviour is the comments from Jonathan Wakely here:
>>>> > https://stackoverflow.com/questions/14268080/cancelling-a-thread-that-has-a-mutex-locked-does-not-unlock-the-mutex
>>>> > In particular: "It interacts with noexcept as you'd expect:
>>>> > std::terminate() is called if a __forced_unwind escapes a noexcept
>>>> > function, so noexcept functions are really noexcept, they won't
>>>> > unexpectedly throw some 'special' type"
>>>> > Which does seem logical, but unless I'm missing something this makes
>>>> > it unsafe to perform any operation in a destructor which might cross
>>>> > a cancellation point, unless that destructor is noexcept(false).
>>>> Unfortunately I still think that's true.
>>>> This was also raised in https://gcc.gnu.org/ml/gcc-help/2015-08/msg00040.html
>>> Ouch. Had you considered the option of having any scope that is
>>> noexcept(true) also be treated as if it was implicitly in a scoped
>>> pthread_setcancelstate(PTHREAD_CANCEL_DISABLE), restoring the
>>> old state when it leaves that scope?
>>> Would it be feasible for the compiler to automatically generate that?
>>> For any toolchain which does use the unwinding exceptions extension,
>>> that also seems like a logical extension to the noexcept behaviour,
>>> since allowing cancellation will otherwise result in an exception and
>>> process termination. If people really need cancellation in such
>>> scopes, then they can more manageably mark just those noexcept(false).
>>> It would need to be done by the compiler, since in user code I can't
>>> do that in a destructor in a way that will also protect unwinding
>>> members of a class (which may have destructors in code I don't
>>> I can't even completely mitigate this by just always using -std=c++03
>>> because presumably I'm also exposed to (at least) libstdc++.so being
>>> built with the new compiler default of C++14 or later.
>>> I'd be really sad to lose the stack unwinding we currently have when
>>> a thread is cancelled. I've always known it was an extension (and I'm
>>> still a bit surprised it hasn't become part of the official standard),
>>> but it is fairly portable in practice.
>>> On Linux (or on Debian at least) clang also supports it. It's also
>>> supported by gcc on FreeBSD and MacOS (though not by clang there).
>>> It's supported by mingw for Windows builds. OpenBSD is currently
>>> the only platform I know of where even its gcc toolchain doesn't
>>> support this (but they're also missing support for standard locale
>>> functionality so it's a special snowflake anyway).
>>> It seems that we need to find some way past the status-quo though,
>>> because "don't ever use pthread_cancel" is the same as saying that
>>> there's no longer any use for the forced_unwind extension. Or that
>>> "you can have a pthread_cancel which leaks resources, or none at all".
>>> Having a pthread_cancel that only works on cancellation points that
>>> aren't noexcept seems like a reasonable compromise and extension to
>>> the shortcomings of the standard to me. Am I missing something there
>>> which makes that solution not a viable option either?
>> Have glibc override the abort () from the forced_unwind if in pthread_cancel
> If the forced_unwind exception escapes a noexcept function then the
> compiler calls std::terminate(). That can be replaced by the user so
> that it doesn't call abort(). It must not return, but a user-supplied
> terminate handler could trap or raise SIGKILL or something else.
> Required behavior: A terminate_handler shall terminate execution of
> the program without returning
> to the caller.
> Default behavior: The implementation’s default terminate_handler calls abort().
> I don't think glibc can help, I think the compiler would need to
> change to not call std::terminate().
Maybe it could call an unwinder provided hook so that forced_unwind can
set it to sth stopping the unwinding and signalling an error rather than