about summary refs log tree commit diff
path: root/hurd/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/hurd
parent53432762ac2ff24794089e2c767b976e54c2dc0a (diff)
downloadglibc-5c06743c8a6f2184fbd3792b13dffa30f473b7b7.tar.gz
glibc-5c06743c8a6f2184fbd3792b13dffa30f473b7b7.tar.xz
glibc-5c06743c8a6f2184fbd3792b13dffa30f473b7b7.zip
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/hurd')
-rw-r--r--hurd/hurd/signal.h19
1 files changed, 15 insertions, 4 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))