From owner-svn-src-all@FreeBSD.ORG Sun Sep 19 09:03:11 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DED41106566B; Sun, 19 Sep 2010 09:03:11 +0000 (UTC) (envelope-from davidxu@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id CE6B18FC17; Sun, 19 Sep 2010 09:03:11 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o8J93B7X095214; Sun, 19 Sep 2010 09:03:11 GMT (envelope-from davidxu@svn.freebsd.org) Received: (from davidxu@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o8J93BTx095209; Sun, 19 Sep 2010 09:03:11 GMT (envelope-from davidxu@svn.freebsd.org) Message-Id: <201009190903.o8J93BTx095209@svn.freebsd.org> From: David Xu Date: Sun, 19 Sep 2010 09:03:11 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r212841 - head/lib/libthr/thread X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 19 Sep 2010 09:03:12 -0000 Author: davidxu Date: Sun Sep 19 09:03:11 2010 New Revision: 212841 URL: http://svn.freebsd.org/changeset/base/212841 Log: Because atfork lock is held while forking, a thread cancellation triggered by atfork handler is unsafe, use intenal flag no_cancel to disable it. Modified: head/lib/libthr/thread/thr_exit.c head/lib/libthr/thread/thr_fork.c head/lib/libthr/thread/thr_private.h head/lib/libthr/thread/thr_sig.c Modified: head/lib/libthr/thread/thr_exit.c ============================================================================== --- head/lib/libthr/thread/thr_exit.c Sun Sep 19 08:55:36 2010 (r212840) +++ head/lib/libthr/thread/thr_exit.c Sun Sep 19 09:03:11 2010 (r212841) @@ -206,7 +206,7 @@ _pthread_exit_mask(void *status, sigset_ /* Flag this thread as exiting. */ curthread->cancelling = 1; - curthread->cancel_enable = 0; + curthread->no_cancel = 1; curthread->cancel_async = 0; curthread->cancel_point = 0; if (mask != NULL) Modified: head/lib/libthr/thread/thr_fork.c ============================================================================== --- head/lib/libthr/thread/thr_fork.c Sun Sep 19 08:55:36 2010 (r212840) +++ head/lib/libthr/thread/thr_fork.c Sun Sep 19 09:03:11 2010 (r212841) @@ -137,7 +137,7 @@ _fork(void) struct pthread *curthread; struct pthread_atfork *af; pid_t ret; - int errsave; + int errsave, cancelsave; int was_threaded; int rtld_locks[MAX_RTLD_LOCKS]; @@ -145,7 +145,8 @@ _fork(void) return (__sys_fork()); curthread = _get_curthread(); - + cancelsave = curthread->no_cancel; + curthread->no_cancel = 1; _thr_rwl_rdlock(&_thr_atfork_lock); /* Run down atfork prepare handlers. */ @@ -223,6 +224,7 @@ _fork(void) af->child(); } _thr_rwlock_unlock(&_thr_atfork_lock); + curthread->no_cancel = cancelsave; } else { /* Parent process */ errsave = errno; @@ -244,6 +246,9 @@ _fork(void) } _thr_rwlock_unlock(&_thr_atfork_lock); + curthread->no_cancel = cancelsave; + /* test async cancel */ + _thr_testcancel(curthread); } errno = errsave; Modified: head/lib/libthr/thread/thr_private.h ============================================================================== --- head/lib/libthr/thread/thr_private.h Sun Sep 19 08:55:36 2010 (r212840) +++ head/lib/libthr/thread/thr_private.h Sun Sep 19 09:03:11 2010 (r212841) @@ -356,9 +356,9 @@ struct pthread { struct pthread_attr attr; #define SHOULD_CANCEL(thr) \ - ((thr)->cancel_pending && \ + ((thr)->cancel_pending && (thr)->cancel_enable && \ ((thr)->cancel_point || (thr)->cancel_async) && \ - (thr)->cancel_enable && (thr)->cancelling == 0) + (thr)->no_cancel == 0) /* Cancellation is enabled */ int cancel_enable; @@ -369,8 +369,8 @@ struct pthread { /* Thread is at cancellation point */ int cancel_point; - /* Cancellation should be synchoronized */ - int cancel_defer; + /* Cancellation is temporarily disabled */ + int no_cancel; /* Asynchronouse cancellation is enabled */ int cancel_async; Modified: head/lib/libthr/thread/thr_sig.c ============================================================================== --- head/lib/libthr/thread/thr_sig.c Sun Sep 19 08:55:36 2010 (r212840) +++ head/lib/libthr/thread/thr_sig.c Sun Sep 19 09:03:11 2010 (r212841) @@ -187,7 +187,6 @@ handle_signal(struct sigaction *actp, in struct pthread *curthread = _get_curthread(); ucontext_t uc2; __siginfohandler_t *sigfunc; - int cancel_defer; int cancel_point; int cancel_async; int cancel_enable; @@ -213,12 +212,10 @@ handle_signal(struct sigaction *actp, in * cancellation is pending, to avoid this problem while thread is in * deferring mode, cancellation is temporarily disabled. */ - cancel_defer = curthread->cancel_defer; cancel_point = curthread->cancel_point; cancel_async = curthread->cancel_async; cancel_enable = curthread->cancel_enable; curthread->cancel_point = 0; - curthread->cancel_defer = 0; if (!cancel_async) curthread->cancel_enable = 0; @@ -245,7 +242,6 @@ handle_signal(struct sigaction *actp, in err = errno; curthread->in_sigsuspend = in_sigsuspend; - curthread->cancel_defer = cancel_defer; curthread->cancel_point = cancel_point; curthread->cancel_enable = cancel_enable; @@ -275,7 +271,7 @@ check_cancel(struct pthread *curthread, { if (__predict_true(!curthread->cancel_pending || !curthread->cancel_enable || - curthread->cancelling)) + curthread->no_cancel)) return; if (curthread->cancel_async) {