We can no longer afford to keep stale sigstate structures in the
_hurd_sigstates list if some of them are marked as global receivers,
otherwise we might try to use them to deliver signals.
* hurd/hurdsig.c (_hurd_sigstate_delete): New function. Remove a sigstate
from the list and release its memory. To be used by libpthread at thread
destruction time.
* hurd/Versions (_hurd_sigstate_delete): Add the new symbol.
* hurd/hurd/signal.h (_hurd_sigstate_delete): Add its prototype.
---
hurd/Versions | 1 +
hurd/hurd/signal.h | 3 +++
hurd/hurdsig.c | 22 ++++++++++++++++++++++
3 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/hurd/Versions b/hurd/Versions
index fe65d25..ec405db 100644
--- a/hurd/Versions
+++ b/hurd/Versions
@@ -162,6 +162,7 @@ libc {
_hurd_sigstate_lock;
_hurd_sigstate_pending;
_hurd_sigstate_unlock;
+ _hurd_sigstate_delete;
}
%if !SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h
index 6b4d695..1c4733a 100644
--- a/hurd/hurd/signal.h
+++ b/hurd/hurd/signal.h
@@ -150,6 +150,9 @@ extern struct sigaction *_hurd_sigstate_actions (struct
hurd_sigstate *ss);
extern sigset_t _hurd_sigstate_pending (const struct hurd_sigstate *ss);
extern void _hurd_sigstate_unlock (struct hurd_sigstate *ss);
+/* Used by libpthread to remove stale sigstate structures. */
+extern void _hurd_sigstate_delete (thread_t thread);
+
#ifndef _HURD_SIGNAL_H_EXTERN_INLINE
#define _HURD_SIGNAL_H_EXTERN_INLINE __extern_inline
#endif
diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c
index eaf5ac1..f5fa659 100644
--- a/hurd/hurdsig.c
+++ b/hurd/hurdsig.c
@@ -126,6 +126,28 @@ _hurd_thread_sigstate (thread_t thread)
return ss;
}
+/* 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.) */
+void
+_hurd_sigstate_delete (thread_t thread)
+{
+ struct hurd_sigstate **ssp, *ss;
+
+ __mutex_lock (&_hurd_siglock);
+ for (ssp = &_hurd_sigstates; *ssp; ssp = &(*ssp)->next)
+ if ((*ssp)->thread == thread)
+ break;
+
+ ss = *ssp;
+ if (ss)
+ *ssp = ss->next;
+
+ __mutex_unlock (&_hurd_siglock);
+ if (ss)
+ free (ss);
+}
+
/* Make SS a global receiver, with pthread signal semantics. */
void
_hurd_sigstate_set_global_rcv (struct hurd_sigstate *ss)
--
1.7.5.3