On Tue, Aug 15, 2017 at 1:28 PM, Jonathan Wakely <jwakely....@gmail.com> wrote: > On 15 August 2017 at 11:24, Richard Biener <richard.guent...@gmail.com> wrote: >> On Tue, Aug 15, 2017 at 6:44 AM, Ron <r...@bitbabbler.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 >>> control). >>> >>> 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 >> 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().
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 abort()ing. Richard.