diff options
| author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2025-03-15 15:23:42 +0000 |
|---|---|---|
| committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2025-03-15 19:45:55 +0000 |
| commit | bfb2f2f481147da54237ade3266f2586a51d43c9 (patch) | |
| tree | f8e7e916730d939eb9e1737bdc411e5a8101b559 | |
| parent | 10af00f7a135c85796a9c4c75228358b8898da5c (diff) | |
| download | glibc-bfb2f2f481147da54237ade3266f2586a51d43c9.tar.xz glibc-bfb2f2f481147da54237ade3266f2586a51d43c9.zip | |
htl: Make pthread_setcanceltype / state a cancellation point
as expected by tst-cancel32.
| -rw-r--r-- | htl/pt-setcancelstate.c | 8 | ||||
| -rw-r--r-- | htl/pt-setcanceltype.c | 5 | ||||
| -rw-r--r-- | sysdeps/htl/pthreadP.h | 8 |
3 files changed, 21 insertions, 0 deletions
diff --git a/htl/pt-setcancelstate.c b/htl/pt-setcancelstate.c index 6e09c260ea..0d5692e661 100644 --- a/htl/pt-setcancelstate.c +++ b/htl/pt-setcancelstate.c @@ -24,6 +24,7 @@ int __pthread_setcancelstate (int state, int *oldstate) { struct __pthread *p = _pthread_self (); + int cancelled; switch (state) { @@ -38,8 +39,15 @@ __pthread_setcancelstate (int state, int *oldstate) if (oldstate != NULL) *oldstate = p->cancel_state; p->cancel_state = state; + cancelled = (p->cancel_state == PTHREAD_CANCEL_ENABLE) && p->cancel_pending == 1 && (p->cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS); + if (cancelled) + /* Do not achieve cancel when called again, notably from __pthread_exit itself. */ + p->cancel_pending = 2; __pthread_mutex_unlock (&p->cancel_lock); + if (cancelled && __pthread_exit) + __pthread_exit (PTHREAD_CANCELED); + return 0; } libc_hidden_def (__pthread_setcancelstate) diff --git a/htl/pt-setcanceltype.c b/htl/pt-setcanceltype.c index 0b76fbfbd6..b33931c468 100644 --- a/htl/pt-setcanceltype.c +++ b/htl/pt-setcanceltype.c @@ -24,6 +24,7 @@ int __pthread_setcanceltype (int type, int *oldtype) { struct __pthread *p = _pthread_self (); + int cancelled; switch (type) { @@ -38,8 +39,12 @@ __pthread_setcanceltype (int type, int *oldtype) if (oldtype != NULL) *oldtype = p->cancel_type; p->cancel_type = type; + cancelled = (p->cancel_state == PTHREAD_CANCEL_ENABLE) && p->cancel_pending && (p->cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS); __pthread_mutex_unlock (&p->cancel_lock); + if (cancelled && __pthread_exit) + __pthread_exit (PTHREAD_CANCELED); + return 0; } libc_hidden_def (__pthread_setcanceltype) diff --git a/sysdeps/htl/pthreadP.h b/sysdeps/htl/pthreadP.h index 9479b9ef24..78ef4e7674 100644 --- a/sysdeps/htl/pthreadP.h +++ b/sysdeps/htl/pthreadP.h @@ -221,6 +221,14 @@ hidden_proto (__pthread_setspecific) hidden_proto (__pthread_get_cleanup_stack) #endif +#if !defined(__NO_WEAK_PTHREAD_ALIASES) && !IS_IN (libpthread) +# ifdef weak_extern +weak_extern (__pthread_exit) +# else +# pragma weak __pthread_exit +# endif +#endif + #define ASSERT_TYPE_SIZE(type, size) \ _Static_assert (sizeof (type) == size, \ "sizeof (" #type ") != " #size) |
