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:
parent
daa9ae80c8
commit
585e6320d2
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user