aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2025-03-15 15:23:42 +0000
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2025-03-15 19:45:55 +0000
commitbfb2f2f481147da54237ade3266f2586a51d43c9 (patch)
treef8e7e916730d939eb9e1737bdc411e5a8101b559
parent10af00f7a135c85796a9c4c75228358b8898da5c (diff)
downloadglibc-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.c8
-rw-r--r--htl/pt-setcanceltype.c5
-rw-r--r--sysdeps/htl/pthreadP.h8
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)