This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Behaviour of __forced_unwind with noexcept

On 15 August 2017 at 11:24, Richard Biener <> wrote:
> On Tue, Aug 15, 2017 at 6:44 AM, Ron <> 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:
>>> >
>>> >
>>> >
>>> > 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
>> 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
>> control).
>> I can't even completely mitigate this by just always using -std=c++03
>> because presumably I'm also exposed to (at least) 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
> context?

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().

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]