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.
This commit is contained in:
David Xu 2010-09-21 06:47:04 +00:00
parent 68653c3bd6
commit 81f3e99c56
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=212952

View File

@ -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);
}
}
}