summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2023-02-11 09:54:12 -0500
committerRich Felker <dalias@aerifal.cx>2023-02-11 13:00:22 -0500
commitc3cd04fa5fecd2c349aefde090c602554ee4fa24 (patch)
treea8ecb18938c7fd424d2be79537c73688d84fec3d
parent115149c023485a69f5bff05efd5339c0c5f77798 (diff)
downloadmusl-c3cd04fa5fecd2c349aefde090c602554ee4fa24.tar.gz
fix pthread_detach inadvertently acting as cancellation point in race case
disabling cancellation around the pthread_join call seems to be the safest and logically simplest fix. i believe it would also be possible to just perform the unmap directly here after __tl_sync, removing the dependency on pthread_join, but such an approach duplicately encodes a lot more implementation assumptions.
-rw-r--r--src/thread/pthread_detach.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/src/thread/pthread_detach.c b/src/thread/pthread_detach.c
index 77772af2..d73a500e 100644
--- a/src/thread/pthread_detach.c
+++ b/src/thread/pthread_detach.c
@@ -5,8 +5,12 @@ static int __pthread_detach(pthread_t t)
{
/* If the cas fails, detach state is either already-detached
* or exiting/exited, and pthread_join will trap or cleanup. */
- if (a_cas(&t->detach_state, DT_JOINABLE, DT_DETACHED) != DT_JOINABLE)
- return __pthread_join(t, 0);
+ if (a_cas(&t->detach_state, DT_JOINABLE, DT_DETACHED) != DT_JOINABLE) {
+ int cs;
+ __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+ __pthread_join(t, 0);
+ __pthread_setcancelstate(cs, 0);
+ }
return 0;
}