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