summaryrefslogtreecommitdiff
path: root/hurd
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2020-12-21 02:10:16 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2020-12-21 02:10:16 +0100
commit5c06743c8a6f2184fbd3792b13dffa30f473b7b7 (patch)
tree07a16aeb17241b84b149ea13a19861f214b945b1 /hurd
parent53432762ac2ff24794089e2c767b976e54c2dc0a (diff)
downloadglibc-5c06743c8a6f2184fbd3792b13dffa30f473b7b7.tar.gz
Hurd: make sigstates hold a reference on thread ports
This change is required in order to correctly release per-thread resources. Directly reusing the threading library reference isn't possible since the sigstate is also used early in the main thread, before threading is initialized. * hurd/hurd/signal.h (_hurd_self_sigstate): Drop thread reference after calling _hurd_thread_sigstate. (_hurd_critical_section_lock): Likewise. * hurd/hurdsig.c (_hurd_thread_sigstate): Add a reference on the thread. (_hurd_sigstate_delete): Drop thread reference.
Diffstat (limited to 'hurd')
-rw-r--r--hurd/hurd/signal.h19
-rw-r--r--hurd/hurdsig.c17
2 files changed, 29 insertions, 7 deletions
diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h
index f6f91218db..2a0aa20b72 100644
--- a/hurd/hurd/signal.h
+++ b/hurd/hurd/signal.h
@@ -67,7 +67,9 @@ struct hurd_sigstate
spin_lock_t lock; /* Locks most of the rest of the structure. */
+ /* The signal state holds a reference on the thread port. */
thread_t thread;
+
struct hurd_sigstate *next; /* Linked-list of thread sigstates. */
sigset_t blocked; /* What signals are blocked. */
@@ -119,7 +121,9 @@ struct hurd_sigstate
extern struct hurd_sigstate *_hurd_sigstates;
-/* Get the sigstate of a given thread, taking its lock. */
+/* Get the sigstate of a given thread. If there was no sigstate for
+ the thread, one is created, and the thread gains a reference. If
+ the given thread is MACH_PORT_NULL, return the global sigstate. */
extern struct hurd_sigstate *_hurd_thread_sigstate (thread_t);
@@ -162,7 +166,11 @@ _HURD_SIGNAL_H_EXTERN_INLINE struct hurd_sigstate *
_hurd_self_sigstate (void)
{
if (THREAD_GETMEM (THREAD_SELF, _hurd_sigstate) == NULL)
- THREAD_SETMEM (THREAD_SELF, _hurd_sigstate, _hurd_thread_sigstate (__mach_thread_self ()));
+ {
+ thread_t self = __mach_thread_self ();
+ THREAD_SETMEM (THREAD_SELF, _hurd_sigstate, _hurd_thread_sigstate (self));
+ __mach_port_deallocate (__mach_task_self (), self);
+ }
return THREAD_GETMEM (THREAD_SELF, _hurd_sigstate);
}
# endif
@@ -210,12 +218,15 @@ _hurd_critical_section_lock (void)
ss = THREAD_GETMEM (THREAD_SELF, _hurd_sigstate);
if (ss == NULL)
{
+ thread_t self = __mach_thread_self ();
+
/* The thread variable is unset; this must be the first time we've
asked for it. In this case, the critical section flag cannot
possible already be set. Look up our sigstate structure the slow
way. */
- ss = _hurd_thread_sigstate (__mach_thread_self ());
- THREAD_SETMEM(THREAD_SELF, _hurd_sigstate, ss);
+ ss = _hurd_thread_sigstate (self);
+ THREAD_SETMEM (THREAD_SELF, _hurd_sigstate, ss);
+ __mach_port_deallocate (__mach_task_self (), self);
}
if (! __spin_try_lock (&ss->critical_section_lock))
diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c
index 852ae7e441..6fdbf383ee 100644
--- a/hurd/hurdsig.c
+++ b/hurd/hurdsig.c
@@ -114,6 +114,8 @@ _hurd_thread_sigstate (thread_t thread)
}
else
{
+ error_t err;
+
/* Use the global actions as a default for new threads. */
struct hurd_sigstate *s = _hurd_global_sigstate;
if (s)
@@ -127,6 +129,11 @@ _hurd_thread_sigstate (thread_t thread)
ss->next = _hurd_sigstates;
_hurd_sigstates = ss;
+
+ err = __mach_port_mod_refs (__mach_task_self (), thread,
+ MACH_PORT_RIGHT_SEND, 1);
+ if (err)
+ __libc_fatal ("hurd: Can't add reference on Mach thread\n");
}
}
__mutex_unlock (&_hurd_siglock);
@@ -135,8 +142,7 @@ _hurd_thread_sigstate (thread_t thread)
libc_hidden_def (_hurd_thread_sigstate)
/* Destroy a sigstate structure. Called by libpthread just before the
- * corresponding thread is terminated (the kernel thread port must remain valid
- * until this function is called.) */
+ * corresponding thread is terminated. */
void
_hurd_sigstate_delete (thread_t thread)
{
@@ -153,7 +159,12 @@ _hurd_sigstate_delete (thread_t thread)
__mutex_unlock (&_hurd_siglock);
if (ss)
- free (ss);
+ {
+ if (ss->thread != MACH_PORT_NULL)
+ __mach_port_deallocate (__mach_task_self (), ss->thread);
+
+ free (ss);
+ }
}
/* Make SS a global receiver, with pthread signal semantics. */