From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/7083 Path: news.gmane.org!not-for-mail From: Rich Felker Newsgroups: gmane.linux.lib.musl.general Subject: Re: Masked cancellation mode draft Date: Sun, 22 Feb 2015 14:10:00 -0500 Message-ID: <20150222191000.GZ23507@brightrain.aerifal.cx> References: <20150222032453.GA14201@brightrain.aerifal.cx> <20150222175146.GV32724@port70.net> Reply-To: musl@lists.openwall.com NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1424632226 32240 80.91.229.3 (22 Feb 2015 19:10:26 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sun, 22 Feb 2015 19:10:26 +0000 (UTC) To: musl@lists.openwall.com Original-X-From: musl-return-7096-gllmg-musl=m.gmane.org@lists.openwall.com Sun Feb 22 20:10:20 2015 Return-path: Envelope-to: gllmg-musl@m.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by plane.gmane.org with smtp (Exim 4.69) (envelope-from ) id 1YPbv1-0006si-7Z for gllmg-musl@m.gmane.org; Sun, 22 Feb 2015 20:10:19 +0100 Original-Received: (qmail 9332 invoked by uid 550); 22 Feb 2015 19:10:17 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Original-Received: (qmail 9287 invoked from network); 22 Feb 2015 19:10:13 -0000 Content-Disposition: inline In-Reply-To: <20150222175146.GV32724@port70.net> User-Agent: Mutt/1.5.21 (2010-09-15) Original-Sender: Rich Felker Xref: news.gmane.org gmane.linux.lib.musl.general:7083 Archived-At: On Sun, Feb 22, 2015 at 06:51:47PM +0100, Szabolcs Nagy wrote: > * Rich Felker [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