1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
From: Richard Braun <rbraun@sceen.net>
Subject: [PATCH] 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.
---
hurd/hurd/signal.h | 17 ++++++++++++++---
hurd/hurdsig.c | 17 ++++++++++++++---
2 files changed, 28 insertions(+), 6 deletions(-)
--- a/hurd/hurd/signal.h
+++ b/hurd/hurd/signal.h
@@ -63,7 +63,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. */
@@ -117,7 +119,9 @@ extern struct hurd_sigstate *_hurd_sigst
extern struct mutex _hurd_siglock; /* Locks _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);
@@ -158,7 +162,11 @@ _HURD_SIGNAL_H_EXTERN_INLINE struct hurd
_hurd_self_sigstate (void)
{
if (THREAD_SELF->_hurd_sigstate == NULL)
- THREAD_SELF->_hurd_sigstate = _hurd_thread_sigstate (__mach_thread_self ());
+ {
+ thread_t self = __mach_thread_self ();
+ THREAD_SELF->_hurd_sigstate = _hurd_thread_sigstate (self);
+ __mach_port_deallocate (__mach_task_self (), self);
+ }
return THREAD_SELF->_hurd_sigstate;
}
@@ -195,11 +203,14 @@ _hurd_critical_section_lock (void)
ss = 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 = THREAD_SELF->_hurd_sigstate = _hurd_thread_sigstate (__mach_thread_self ());
+ ss = THREAD_SELF->_hurd_sigstate = _hurd_thread_sigstate (self);
+ __mach_port_deallocate (__mach_task_self (), self);
}
if (! __spin_try_lock (&ss->critical_section_lock))
--- a/hurd/hurdsig.c
+++ b/hurd/hurdsig.c
@@ -107,6 +107,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)
@@ -120,6 +122,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);
@@ -127,8 +134,7 @@ _hurd_thread_sigstate (thread_t thread)
}
/* 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)
{
@@ -145,7 +151,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);
+ }
}
versioned_symbol (libc, __hurd_sigstate_delete, _hurd_sigstate_delete, GLIBC_2_21);
#if SHLIB_COMPAT (libc, GLIBC_2_13, GLIBC_2_21)
|