|
Message-ID: <20150222191000.GZ23507@brightrain.aerifal.cx> Date: Sun, 22 Feb 2015 14:10:00 -0500 From: Rich Felker <dalias@...c.org> To: musl@...ts.openwall.com Subject: Re: Masked cancellation mode draft On Sun, Feb 22, 2015 at 06:51:47PM +0100, Szabolcs Nagy wrote: > * Rich Felker <dalias@...c.org> [2015-02-21 22:24:53 -0500]: > > When the cancellation state is set to MASKED, the first cancellation > > point (other than close, which is special) called with cancellation > > pending, or which has a cancellation request arrive while it's > > blocking, returns with an error of ECANCELED, and sets the > > cancellation state to DISABLE. > > > > Even code which was not specifically written to be cancellation-aware > > is compatible with this behavior. As long as it is responding to > > errors, it will see the error, but will have the full repertoire of > > standard functions available to use while cleaning up and returning > > after the error. If the error is ignored, cancellation will be > > delayed, but the behavior is no worse than what could already happen > > from ignoring errors. > > so it works like a special signal that only acts at blocking calls And unlike portable signal-based approaches, it lacks the race conditions and global state. > since the thread is not forcefully killed, only notified about the > cancellation, the cleanup mechanism is under the control of the > programmer > > this seems like a relevant approach to c11 and c++11 which currently > lack any way to safely cancel blocking threads Yes. > the only difficulty i see is that posix has a lot of cancellation > points (some of which are optional) so code that wants to be > 'masked cancellation safe' should properly do the error handling > at a lot of places (eg some stdio functions like printf maybe > cancellation points and usually not checked for errors directly > only in aggregate through ferror) > > if i understood correctly code that does not want to immediately > act upon masked cancellation (only at specific calls) should reset > the cancellation state with > > pthread_setcancelstate(PTHREAD_CANCEL_MASKED, 0) Library code would do this but with &old_cs rather than 0, then restore the state before exiting. It it wants to actually behave like a POSIX cancellation point, it would do something like: pthread_setcancelstate(old_cs, 0) if (was_canceled) { pthread_testcancel(); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); } Then, if old_cs was PTHREAD_CANCEL_ENABLE, the pthread_testcancel will cause cancellation to be acted upon and the caller's cleanup handlers to run. If old_cs was PTHREAD_CANCEL_MASKED, then pthread_testcancel will do nothing and the subsequent call to set PTHREAD_CANCEL_DISABLE will prevent further ECANCELED from happening (since your caller is going to get its ECANCELED error from the function that's about to return). > and then cancellation is deferred until the next cancellation point. > > another issue is that pthread_testcancel() has no return value so it > cannot be used for non-blocking testing of masked cancel. Indeed, I noticed that. There are stupid ways to test but they're not terribly efficient: lots of cancellation points have timeouts that can be zero, but most of them are likely to result in a syscall if cancellation is not already pending. Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.