diff --git a/lib/libthr/thread/thr_cancel.c b/lib/libthr/thread/thr_cancel.c --- a/lib/libthr/thread/thr_cancel.c +++ b/lib/libthr/thread/thr_cancel.c @@ -83,25 +83,25 @@ _thr_setcancelstate(int state, int *oldstate) { struct pthread *curthread = _get_curthread(); - int oldval; + int oldval, val; - oldval = curthread->cancel_enable; switch (state) { case PTHREAD_CANCEL_DISABLE: - curthread->cancel_enable = 0; + val = 0; break; case PTHREAD_CANCEL_ENABLE: - curthread->cancel_enable = 1; - if (curthread->cancel_async) - testcancel(curthread); + val = 1; break; default: return (EINVAL); } - if (oldstate) { + oldval = atomic_swap_int(&curthread->cancel_enable, val); + if (state == PTHREAD_CANCEL_ENABLE && curthread->cancel_async) + testcancel(curthread); + if (oldstate != NULL) { *oldstate = oldval ? PTHREAD_CANCEL_ENABLE : - PTHREAD_CANCEL_DISABLE; + PTHREAD_CANCEL_DISABLE; } return (0); } @@ -125,9 +125,9 @@ return (EINVAL); } - if (oldtype) { + if (oldtype != NULL) { *oldtype = oldval ? PTHREAD_CANCEL_ASYNCHRONOUS : - PTHREAD_CANCEL_DEFERRED; + PTHREAD_CANCEL_DEFERRED; } return (0); } @@ -166,9 +166,8 @@ _thr_cancel_leave(struct pthread *curthread, int maycancel) { curthread->cancel_point = 0; - if (__predict_false(SHOULD_CANCEL(curthread) && - !THR_IN_CRITICAL(curthread) && maycancel)) - _pthread_exit(PTHREAD_CANCELED); + if (maycancel) + testcancel(curthread); } void diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -562,8 +562,12 @@ /* Deferred threads from pthread_cond_signal. */ unsigned int *defer_waiters[MAX_DEFER_WAITERS]; -#define _pthread_endzero wake_addr + /* rtld thread-local dlerror message and seen control */ + char dlerror_msg[512]; + int dlerror_seen; + +#define _pthread_endzero wake_addr struct wake_addr *wake_addr; #define WAKE_ADDR(td) ((td)->wake_addr) @@ -572,10 +576,6 @@ /* pthread_set/get_name_np */ char *name; - - /* rtld thread-local dlerror message and seen control */ - char dlerror_msg[512]; - int dlerror_seen; }; #define THR_SHOULD_GC(thrd) \ diff --git a/lib/libthr/thread/thr_sig.c b/lib/libthr/thread/thr_sig.c --- a/lib/libthr/thread/thr_sig.c +++ b/lib/libthr/thread/thr_sig.c @@ -185,8 +185,7 @@ } static void -sigcancel_handler(int sig __unused, - siginfo_t *info __unused, ucontext_t *ucp) +sigcancel_handler(int sig __unused, siginfo_t *info __unused, ucontext_t *ucp) { struct pthread *curthread = _get_curthread(); int err; @@ -354,9 +353,11 @@ * 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; + if (curthread->in_sigsuspend) { + if (ucp != NULL) { + SIGADDSET(ucp->uc_sigmask, SIGCANCEL); + curthread->unblock_sigcancel = 1; + } _thr_send_sig(curthread, SIGCANCEL); } else thr_wake(curthread->tid); @@ -365,8 +366,8 @@ * asynchronous cancellation mode, act upon * immediately. */ - _pthread_exit_mask(PTHREAD_CANCELED, - ucp? &ucp->uc_sigmask : NULL); + _pthread_exit_mask(PTHREAD_CANCELED, ucp != NULL ? + &ucp->uc_sigmask : NULL); } } @@ -405,9 +406,8 @@ { uint32_t cycle; - if (__predict_true((curthread->flags & - (THR_FLAGS_NEED_SUSPEND | THR_FLAGS_SUSPENDED)) - != THR_FLAGS_NEED_SUSPEND)) + if (__predict_true((curthread->flags & (THR_FLAGS_NEED_SUSPEND | + THR_FLAGS_SUSPENDED)) != THR_FLAGS_NEED_SUSPEND)) return; if (curthread == _single_thread) return; @@ -664,7 +664,7 @@ } int -_sigsuspend(const sigset_t * set) +_sigsuspend(const sigset_t *set) { sigset_t newset; @@ -672,7 +672,7 @@ } int -__thr_sigsuspend(const sigset_t * set) +__thr_sigsuspend(const sigset_t *set) { struct pthread *curthread; sigset_t newset; @@ -698,7 +698,7 @@ int _sigtimedwait(const sigset_t *set, siginfo_t *info, - const struct timespec * timeout) + const struct timespec *timeout) { sigset_t newset; @@ -713,7 +713,7 @@ */ int __thr_sigtimedwait(const sigset_t *set, siginfo_t *info, - const struct timespec * timeout) + const struct timespec *timeout) { struct pthread *curthread = _get_curthread(); sigset_t newset; diff --git a/share/man/man3/pthread_testcancel.3 b/share/man/man3/pthread_testcancel.3 --- a/share/man/man3/pthread_testcancel.3 +++ b/share/man/man3/pthread_testcancel.3 @@ -34,6 +34,7 @@ .Dv PTHREAD_CANCEL_ENABLE and .Dv PTHREAD_CANCEL_DISABLE . +The function is async-signal-safe. .Pp The .Fn pthread_setcanceltype @@ -248,6 +249,11 @@ .St -p1003.1-96 . The standard allows implementations to make many more functions cancellation points. +.Pp +The +.Fn pthread_setcancelstate +function is async-signal-safe as required by +.St -p1003.1-2024 . .Sh AUTHORS This manual page was written by .An David Leonard Aq Mt d@openbsd.org