diff options
Diffstat (limited to 'hurd/hurdsig.c')
-rw-r--r-- | hurd/hurdsig.c | 93 |
1 files changed, 76 insertions, 17 deletions
diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c index 528343997e..b28c8c80bf 100644 --- a/hurd/hurdsig.c +++ b/hurd/hurdsig.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2016 Free Software Foundation, Inc. +/* Copyright (C) 1991-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -20,9 +20,10 @@ #include <string.h> #include <cthreads.h> /* For `struct mutex'. */ -#include <pthread.h> +#include <pthreadP.h> #include <mach.h> #include <mach/thread_switch.h> +#include <mach/mig_support.h> #include <hurd.h> #include <hurd/id.h> @@ -32,6 +33,8 @@ #include "hurdmalloc.h" /* XXX */ #include "../locale/localeinfo.h" +#include <libc-diag.h> + const char *_hurdsig_getenv (const char *); struct mutex _hurd_siglock; @@ -123,6 +126,7 @@ _hurd_thread_sigstate (thread_t thread) __mutex_unlock (&_hurd_siglock); return ss; } +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 @@ -216,7 +220,6 @@ _hurd_sigstate_actions (struct hurd_sigstate *ss) else return ss->actions; } - /* Signal delivery itself is on this page. */ @@ -343,8 +346,14 @@ interrupted_reply_port_location (thread_t thread, /* Faulted trying to read the TCB. */ return NULL; + DIAG_PUSH_NEEDS_COMMENT; + /* GCC 6 and before seem to be confused by the setjmp call inside + _hurdsig_catch_memory_fault and think that we may be returning a second + time to here with portloc uninitialized (but we never do). */ + DIAG_IGNORE_NEEDS_COMMENT (6, "-Wmaybe-uninitialized"); /* Fault now if this pointer is bogus. */ *(volatile mach_port_t *) portloc = *portloc; + DIAG_POP_NEEDS_COMMENT; if (sigthread) _hurdsig_end_catch_fault (); @@ -1218,6 +1227,55 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss, ss = post_signal (ss, signo, detail, untraced, reply); if (! ss) return; + /* No pending signals left undelivered for this thread. + If we were sent signal 0, we need to check for pending + signals for all threads. */ + if (signo == 0) + { + __spin_unlock (&ss->lock); + __mutex_lock (&_hurd_siglock); + for (ss = _hurd_sigstates; ss != NULL; ss = ss->next) + { + __spin_lock (&ss->lock); + for (signo = 1; signo < NSIG; ++signo) + if (__sigismember (&ss->pending, signo) + && (!__sigismember (&ss->blocked, signo) + /* We "deliver" immediately pending blocked signals whose + action might be to ignore, so that if ignored they are + dropped right away. */ + || ss->actions[signo].sa_handler == SIG_IGN + || ss->actions[signo].sa_handler == SIG_DFL)) + { + __mutex_unlock (&_hurd_siglock); + goto deliver_pending; + } + __spin_unlock (&ss->lock); + } + __mutex_unlock (&_hurd_siglock); + } + else + { + /* No more signals pending; SS->lock is still locked. + Wake up any sigsuspend call that is blocking SS->thread. */ + if (ss->suspended != MACH_PORT_NULL) + { + /* There is a sigsuspend waiting. Tell it to wake up. */ + error_t err; + mach_msg_header_t msg; + msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0); + msg.msgh_remote_port = ss->suspended; + msg.msgh_local_port = MACH_PORT_NULL; + /* These values do not matter. */ + msg.msgh_id = 8675309; /* Jenny, Jenny. */ + ss->suspended = MACH_PORT_NULL; + err = __mach_msg (&msg, MACH_SEND_MSG, sizeof msg, 0, + MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + assert_perror (err); + } + __spin_unlock (&ss->lock); + } + } /* The signal was neither fatal nor traced. We still hold SS->lock. */ if (signo != 0 && ss->thread != MACH_PORT_NULL) @@ -1456,11 +1514,8 @@ _hurdsig_init (const int *intarray, size_t intarraysize) /* Start the signal thread listening on the message port. */ -#pragma weak cthread_fork -#pragma weak cthread_detach -#pragma weak pthread_getattr_np -#pragma weak pthread_attr_getstack - if (!cthread_fork) +#pragma weak __cthread_fork + if (!__cthread_fork) { err = __thread_create (__mach_task_self (), &_hurd_msgport_thread); assert_perror (err); @@ -1485,7 +1540,6 @@ _hurdsig_init (const int *intarray, size_t intarraysize) } else { - cthread_t thread; /* When cthreads is being used, we need to make the signal thread a proper cthread. Otherwise it cannot use mutex_lock et al, which will be the cthreads versions. Various of the message port RPC @@ -1495,17 +1549,22 @@ _hurdsig_init (const int *intarray, size_t intarraysize) we'll let the signal thread's per-thread variables be found as for any normal cthread, and just leave the magic __hurd_sigthread_* values all zero so they'll be ignored. */ - cthread_detach (thread = cthread_fork ((cthread_fn_t) &_hurd_msgport_receive, 0)); - - if (pthread_getattr_np) +#pragma weak __cthread_detach +#pragma weak __pthread_getattr_np +#pragma weak __pthread_attr_getstack + __cthread_t thread = __cthread_fork ( + (cthread_fn_t) &_hurd_msgport_receive, 0); + __cthread_detach (thread); + + if (__pthread_getattr_np) { - /* Record stack layout for fork() */ + /* Record signal thread stack layout for fork() */ pthread_attr_t attr; void *addr; size_t size; - pthread_getattr_np ((pthread_t) thread, &attr); - pthread_attr_getstack (&attr, &addr, &size); + __pthread_getattr_np ((pthread_t) thread, &attr); + __pthread_attr_getstack (&attr, &addr, &size); __hurd_sigthread_stack_base = (uintptr_t) addr; __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + size; } @@ -1561,14 +1620,14 @@ reauth_proc (mach_port_t new) __mach_port_destroy (__mach_task_self (), ref); /* Set the owner of the process here too. */ - mutex_lock (&_hurd_id.lock); + __mutex_lock (&_hurd_id.lock); if (!_hurd_check_ids ()) HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC], __proc_setowner (port, (_hurd_id.gen.nuids ? _hurd_id.gen.uids[0] : 0), !_hurd_id.gen.nuids)); - mutex_unlock (&_hurd_id.lock); + __mutex_unlock (&_hurd_id.lock); (void) &reauth_proc; /* Silence compiler warning. */ } |