Author: davidxu Date: Tue Sep 21 06:47:04 2010 New Revision: 212952 URL: http://svn.freebsd.org/changeset/base/212952
Log: If we are at cancellation point, always work as deferred mode despite whether asynchronous mode is turned on or not, this always gives us a chance to decide whether thread should be canceled or not in cancellation points. Modified: head/lib/libthr/thread/thr_sig.c Modified: head/lib/libthr/thread/thr_sig.c ============================================================================== --- head/lib/libthr/thread/thr_sig.c Tue Sep 21 05:58:45 2010 (r212951) +++ head/lib/libthr/thread/thr_sig.c Tue Sep 21 06:47:04 2010 (r212952) @@ -270,46 +270,44 @@ static void check_cancel(struct pthread *curthread, ucontext_t *ucp) { - if (__predict_true(!curthread->cancel_pending || !curthread->cancel_enable || - curthread->no_cancel)) + if (__predict_true(!curthread->cancel_pending || + !curthread->cancel_enable || curthread->no_cancel)) return; - if (curthread->cancel_async) { + /* + * Otherwise, we are in defer mode, and we are at + * cancel point, tell kernel to not block the current + * thread on next cancelable system call. + * + * There are three cases we should call thr_wake() to + * turn on TDP_WAKEUP or send SIGCANCEL in kernel: + * 1) we are going to call a cancelable system call, + * non-zero cancel_point means we are already in + * cancelable state, next system call is cancelable. + * 2) because _thr_ast() may be called by + * THR_CRITICAL_LEAVE() which is used by rtld rwlock + * and any libthr internal locks, when rtld rwlock + * is used, it is mostly caused my an unresolved PLT. + * those routines may clear the TDP_WAKEUP flag by + * invoking some system calls, in those cases, we + * also should reenable the flag. + * 3) thread is in sigsuspend(), and the syscall insists + * on getting a signal before it agrees to return. + */ + if (curthread->cancel_point) { + if (curthread->in_sigsuspend && ucp) { + SIGADDSET(ucp->uc_sigmask, SIGCANCEL); + curthread->unblock_sigcancel = 1; + _thr_send_sig(curthread, SIGCANCEL); + } else + thr_wake(curthread->tid); + } else if (curthread->cancel_async) { /* - * asynchronous cancellation mode, act upon + * asynchronous cancellation mode, act upon * immediately. - */ + */ _pthread_exit_mask(PTHREAD_CANCELED, ucp? &ucp->uc_sigmask : NULL); - } else { - /* - * Otherwise, we are in defer mode, and we are at - * cancel point, tell kernel to not block the current - * thread on next cancelable system call. - * - * There are three cases we should call thr_wake() to - * turn on TDP_WAKEUP or send SIGCANCEL in kernel: - * 1) we are going to call a cancelable system call, - * non-zero cancel_point means we are already in - * cancelable state, next system call is cancelable. - * 2) because _thr_ast() may be called by - * THR_CRITICAL_LEAVE() which is used by rtld rwlock - * and any libthr internal locks, when rtld rwlock - * is used, it is mostly caused my an unresolved PLT. - * those routines may clear the TDP_WAKEUP flag by - * invoking some system calls, in those cases, we - * also should reenable the flag. - * 3) thread is in sigsuspend(), and the syscall insists - * on getting a signal before it agrees to return. - */ - if (curthread->cancel_point) { - if (curthread->in_sigsuspend && ucp) { - SIGADDSET(ucp->uc_sigmask, SIGCANCEL); - curthread->unblock_sigcancel = 1; - _thr_send_sig(curthread, SIGCANCEL); - } else - thr_wake(curthread->tid); - } } } _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"