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? I guess sprinkling pthread_setcancelstate () around would be doable (in some __cxxabi helper) but it might be quite expensive to do so... Richard. > >> > And since that could be something as simple as logging to stdio and >> > almost impossible to definitely rule out in a future proof way if the >> > destructor does anything non-trivial (like calling functions in a >> > system or other 3rd party library) ... and since the race of catching >> > a cancellation request in such a destructor could be a relatively rare >> > one to lose in a lot of code ... there could be a lot of extant code >> > with new latent 'crasher' bugs when built with GCC 6.1 or later. >> > >> > And/or a lot of people are going to have to go through a lot of code >> > and mark up a lot of methods with noexcept(false). >> > >> > >> > So I'm half-hoping that I am actually missing something here which >> > mitigates that - but if not, is this something we need to give a >> > bit more thought to? >> > >> > (Please keep me cc'd, I'm not currently on this list) >> > >> > Cheers, >> > Ron