summaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2016-10-25 20:30:33 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2016-10-25 20:30:33 +0200
commitab44f817c77c6db55179d074750fab3ac94c4c16 (patch)
tree09b89dd8ff8734f43a4998fca468fd7883c65727 /sysdeps
parent7c08c364b85d24b32460cba978edcecc98722973 (diff)
parent4dc1e6e42f1f602e1d2227e112f2db8dce9da763 (diff)
Merge branch 't/hurdsig-global-dispositions' into refs/top-bases/t/ONSTACK
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/mach/hurd/fork.c24
-rw-r--r--sysdeps/mach/hurd/i386/sigreturn.c10
-rw-r--r--sysdeps/mach/hurd/i386/trampoline.c6
-rw-r--r--sysdeps/mach/hurd/sigaction.c16
-rw-r--r--sysdeps/mach/hurd/sigpending.c6
-rw-r--r--sysdeps/mach/hurd/sigprocmask.c8
-rw-r--r--sysdeps/mach/hurd/sigsuspend.c15
-rw-r--r--sysdeps/mach/hurd/sigwait.c21
-rw-r--r--sysdeps/mach/hurd/spawni.c25
9 files changed, 80 insertions, 51 deletions
diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c
index 3e7501f9a1..82059d6097 100644
--- a/sysdeps/mach/hurd/fork.c
+++ b/sysdeps/mach/hurd/fork.c
@@ -465,6 +465,7 @@ __fork (void)
(err = __mach_port_insert_right (newtask, ss->thread,
thread, MACH_MSG_TYPE_COPY_SEND)))
LOSE;
+ /* XXX consumed? (_hurd_sigthread is no more) */
if (thread_refs > 1 &&
(err = __mach_port_mod_refs (newtask, ss->thread,
MACH_PORT_RIGHT_SEND,
@@ -625,10 +626,6 @@ __fork (void)
for (i = 0; i < _hurd_nports; ++i)
__spin_unlock (&_hurd_ports[i].lock);
- /* We are one of the (exactly) two threads in this new task, we
- will take the task-global signals. */
- _hurd_sigthread = ss->thread;
-
/* Claim our sigstate structure and unchain the rest: the
threads existed in the parent task but don't exist in this
task (the child process). Delay freeing them until later
@@ -648,6 +645,25 @@ __fork (void)
ss->next = NULL;
_hurd_sigstates = ss;
__mutex_unlock (&_hurd_siglock);
+ /* Earlier on, the global sigstate may have been tainted and now needs to
+ be reinitialized. Nobody is interested in its present state anymore:
+ we're not, the signal thread will be restarted, and there are no other
+ threads.
+
+ We can't simply allocate a fresh global sigstate here, as
+ _hurd_thread_sigstate will call malloc and that will deadlock trying
+ to determine the current thread's sigstate. */
+#if 0
+ _hurd_thread_sigstate_init (_hurd_global_sigstate, MACH_PORT_NULL);
+#else
+ /* Only reinitialize the lock -- otherwise we might have to do additional
+ setup as done in hurdsig.c:_hurdsig_init. */
+ __spin_lock_init (&_hurd_global_sigstate->lock);
+#endif
+
+ /* We are one of the (exactly) two threads in this new task, we
+ will take the task-global signals. */
+ _hurd_sigstate_set_global_rcv (ss);
/* Fetch our new process IDs from the proc server. No need to
refetch our pgrp; it is always inherited from the parent (so
diff --git a/sysdeps/mach/hurd/i386/sigreturn.c b/sysdeps/mach/hurd/i386/sigreturn.c
index 0a3af1fdef..83c0246ead 100644
--- a/sysdeps/mach/hurd/i386/sigreturn.c
+++ b/sysdeps/mach/hurd/i386/sigreturn.c
@@ -38,7 +38,7 @@ __sigreturn (struct sigcontext *scp)
}
ss = _hurd_self_sigstate ();
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
/* Remove the link on the `active resources' chain added by
_hurd_setup_sighandler. Its purpose was to make sure
@@ -50,19 +50,19 @@ __sigreturn (struct sigcontext *scp)
ss->intr_port = scp->sc_intr_port;
/* Check for pending signals that were blocked by the old set. */
- if (ss->pending & ~ss->blocked)
+ if (_hurd_sigstate_pending (ss) & ~ss->blocked)
{
/* There are pending signals that just became unblocked. Wake up the
signal thread to deliver them. But first, squirrel away SCP where
the signal thread will notice it if it runs another handler, and
arrange to have us called over again in the new reality. */
ss->context = scp;
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
__msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
/* If a pending signal was handled, sig_post never returned.
If it did return, the pending signal didn't run a handler;
proceed as usual. */
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
ss->context = NULL;
}
@@ -73,7 +73,7 @@ __sigreturn (struct sigcontext *scp)
abort ();
}
else
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
/* Destroy the MiG reply port used by the signal handler, and restore the
reply port in use by the thread when interrupted. */
diff --git a/sysdeps/mach/hurd/i386/trampoline.c b/sysdeps/mach/hurd/i386/trampoline.c
index 5de27564dd..83af77055b 100644
--- a/sysdeps/mach/hurd/i386/trampoline.c
+++ b/sysdeps/mach/hurd/i386/trampoline.c
@@ -74,7 +74,11 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
interrupted RPC frame. */
state->basic.esp = state->basic.uesp;
- if ((ss->actions[signo].sa_flags & SA_ONSTACK) &&
+ /* XXX what if handler != action->handler (for instance, if a signal
+ * preemptor took over) ? */
+ action = & _hurd_sigstate_actions (ss) [signo];
+
+ if ((action->sa_flags & SA_ONSTACK) &&
!(ss->sigaltstack.ss_flags & (SS_DISABLE|SS_ONSTACK)))
{
sigsp = ss->sigaltstack.ss_sp + ss->sigaltstack.ss_size;
diff --git a/sysdeps/mach/hurd/sigaction.c b/sysdeps/mach/hurd/sigaction.c
index 3ff9d183f0..a753082fa4 100644
--- a/sysdeps/mach/hurd/sigaction.c
+++ b/sysdeps/mach/hurd/sigaction.c
@@ -46,15 +46,15 @@ __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
ss = _hurd_self_sigstate ();
__spin_lock (&ss->critical_section_lock);
- __spin_lock (&ss->lock);
- old = ss->actions[sig];
+ _hurd_sigstate_lock (ss);
+ old = _hurd_sigstate_actions (ss) [sig];
if (act != NULL)
- ss->actions[sig] = a;
+ _hurd_sigstate_actions (ss) [sig] = a;
if (act != NULL && sig == SIGCHLD &&
(a.sa_flags & SA_NOCLDSTOP) != (old.sa_flags & SA_NOCLDSTOP))
{
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
/* Inform the proc server whether or not it should send us SIGCHLD for
stopped children. We do this in a critical section so that no
@@ -62,8 +62,8 @@ __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
__USEPORT (PROC,
__proc_mod_stopchild (port, !(a.sa_flags & SA_NOCLDSTOP)));
- __spin_lock (&ss->lock);
- pending = ss->pending & ~ss->blocked;
+ _hurd_sigstate_lock (ss);
+ pending = _hurd_sigstate_pending (ss) & ~ss->blocked;
}
else if (act != NULL && (a.sa_handler == SIG_IGN || a.sa_handler == SIG_DFL))
/* We are changing to an action that might be to ignore SIG signals.
@@ -72,11 +72,11 @@ __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
back and then SIG is unblocked, the signal pending now should not
arrive. So wake up the signal thread to check the new state and do
the right thing. */
- pending = ss->pending & __sigmask (sig);
+ pending = _hurd_sigstate_pending (ss) & __sigmask (sig);
else
pending = 0;
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
__spin_unlock (&ss->critical_section_lock);
if (pending)
diff --git a/sysdeps/mach/hurd/sigpending.c b/sysdeps/mach/hurd/sigpending.c
index ef855329c6..23aca3c681 100644
--- a/sysdeps/mach/hurd/sigpending.c
+++ b/sysdeps/mach/hurd/sigpending.c
@@ -36,9 +36,9 @@ sigpending (sigset_t *set)
}
ss = _hurd_self_sigstate ();
- __spin_lock (&ss->lock);
- pending = ss->pending;
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_lock (ss);
+ pending = _hurd_sigstate_pending (ss);
+ _hurd_sigstate_unlock (ss);
*set = pending;
return 0;
diff --git a/sysdeps/mach/hurd/sigprocmask.c b/sysdeps/mach/hurd/sigprocmask.c
index 9168224b0c..b5f2eba72d 100644
--- a/sysdeps/mach/hurd/sigprocmask.c
+++ b/sysdeps/mach/hurd/sigprocmask.c
@@ -36,7 +36,7 @@ __sigprocmask (int how, const sigset_t *set, sigset_t *oset)
ss = _hurd_self_sigstate ();
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
old = ss->blocked;
@@ -57,7 +57,7 @@ __sigprocmask (int how, const sigset_t *set, sigset_t *oset)
break;
default:
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
errno = EINVAL;
return -1;
}
@@ -65,9 +65,9 @@ __sigprocmask (int how, const sigset_t *set, sigset_t *oset)
ss->blocked &= ~_SIG_CANT_MASK;
}
- pending = ss->pending & ~ss->blocked;
+ pending = _hurd_sigstate_pending (ss) & ~ss->blocked;
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
if (oset != NULL)
*oset = old;
diff --git a/sysdeps/mach/hurd/sigsuspend.c b/sysdeps/mach/hurd/sigsuspend.c
index bafac7e94d..770007c0d8 100644
--- a/sysdeps/mach/hurd/sigsuspend.c
+++ b/sysdeps/mach/hurd/sigsuspend.c
@@ -40,7 +40,7 @@ __sigsuspend (const sigset_t *set)
ss = _hurd_self_sigstate ();
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
oldmask = ss->blocked;
if (set != NULL)
@@ -48,11 +48,11 @@ __sigsuspend (const sigset_t *set)
ss->blocked = newmask & ~_SIG_CANT_MASK;
/* Notice if any pending signals just became unblocked. */
- pending = ss->pending & ~ss->blocked;
+ pending = _hurd_sigstate_pending (ss) & ~ss->blocked;
/* Tell the signal thread to message us when a signal arrives. */
ss->suspended = wait;
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
if (pending)
/* Tell the signal thread to check for pending signals. */
@@ -63,10 +63,11 @@ __sigsuspend (const sigset_t *set)
MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
__mach_port_destroy (__mach_task_self (), wait);
- __spin_lock (&ss->lock);
- ss->blocked = oldmask; /* Restore the old mask. */
- pending = ss->pending & ~ss->blocked; /* Again check for pending signals. */
- __spin_unlock (&ss->lock);
+ /* Restore the old mask and check for pending signals again. */
+ _hurd_sigstate_lock (ss);
+ ss->blocked = oldmask;
+ pending = _hurd_sigstate_pending(ss) & ~ss->blocked;
+ _hurd_sigstate_unlock (ss);
if (pending)
/* Tell the signal thread to check for pending signals. */
diff --git a/sysdeps/mach/hurd/sigwait.c b/sysdeps/mach/hurd/sigwait.c
index ab10913f3a..d277edd3f1 100644
--- a/sysdeps/mach/hurd/sigwait.c
+++ b/sysdeps/mach/hurd/sigwait.c
@@ -27,7 +27,7 @@ int
__sigwait (const sigset_t *set, int *sig)
{
struct hurd_sigstate *ss;
- sigset_t mask, ready;
+ sigset_t mask, ready, blocked;
int signo = 0;
struct hurd_signal_preemptor preemptor;
jmp_buf buf;
@@ -49,8 +49,8 @@ __sigwait (const sigset_t *set, int *sig)
/* Make sure this is all kosher */
assert (__sigismember (&mask, signo));
- /* Make sure this signal is unblocked */
- __sigdelset (&ss->blocked, signo);
+ /* Restore the blocking mask. */
+ ss->blocked = blocked;
return pe->handler;
}
@@ -71,10 +71,11 @@ __sigwait (const sigset_t *set, int *sig)
__sigemptyset (&mask);
ss = _hurd_self_sigstate ();
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
/* See if one of these signals is currently pending. */
- __sigandset (&ready, &ss->pending, &mask);
+ sigset_t pending = _hurd_sigstate_pending (ss);
+ __sigandset (&ready, &pending, &mask);
if (! __sigisemptyset (&ready))
{
for (signo = 1; signo < NSIG; signo++)
@@ -102,7 +103,11 @@ __sigwait (const sigset_t *set, int *sig)
preemptor.next = ss->preemptors;
ss->preemptors = &preemptor;
- __spin_unlock (&ss->lock);
+ /* Unblock the expected signals */
+ blocked = ss->blocked;
+ ss->blocked &= ~mask;
+
+ _hurd_sigstate_unlock (ss);
/* Wait. */
__mach_msg (&msg, MACH_RCV_MSG, 0, sizeof (msg), wait,
@@ -113,7 +118,7 @@ __sigwait (const sigset_t *set, int *sig)
{
assert (signo);
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
/* Delete our preemptor. */
assert (ss->preemptors == &preemptor);
@@ -122,7 +127,7 @@ __sigwait (const sigset_t *set, int *sig)
all_done:
- spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
__mach_port_destroy (__mach_task_self (), wait);
*sig = signo;
diff --git a/sysdeps/mach/hurd/spawni.c b/sysdeps/mach/hurd/spawni.c
index 328a4bb13f..12fa457c02 100644
--- a/sysdeps/mach/hurd/spawni.c
+++ b/sysdeps/mach/hurd/spawni.c
@@ -238,26 +238,29 @@ __spawni (pid_t *pid, const char *file,
assert (! __spin_lock_locked (&ss->critical_section_lock));
__spin_lock (&ss->critical_section_lock);
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
ints[INIT_SIGMASK] = ss->blocked;
- ints[INIT_SIGPENDING] = ss->pending;
+ ints[INIT_SIGPENDING] = _hurd_sigstate_pending (ss); /* XXX really? */
ints[INIT_SIGIGN] = 0;
/* Unless we were asked to reset all handlers to SIG_DFL,
pass down the set of signals that were set to SIG_IGN. */
- if ((flags & POSIX_SPAWN_SETSIGDEF) == 0)
- for (i = 1; i < NSIG; ++i)
- if (ss->actions[i].sa_handler == SIG_IGN)
- ints[INIT_SIGIGN] |= __sigmask (i);
-
- /* We hold the sigstate lock until the exec has failed so that no signal
- can arrive between when we pack the blocked and ignored signals, and
- when the exec actually happens. A signal handler could change what
+ {
+ struct sigaction *actions = _hurd_sigstate_actions (ss);
+ if ((flags & POSIX_SPAWN_SETSIGDEF) == 0)
+ for (i = 1; i < NSIG; ++i)
+ if (actions[i].sa_handler == SIG_IGN)
+ ints[INIT_SIGIGN] |= __sigmask (i);
+ }
+
+ /* We hold the critical section lock until the exec has failed so that no
+ signal can arrive between when we pack the blocked and ignored signals,
+ and when the exec actually happens. A signal handler could change what
signals are blocked and ignored. Either the change will be reflected
in the exec, or the signal will never be delivered. Setting the
critical section flag avoids anything we call trying to acquire the
sigstate lock. */
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
/* Set signal mask. */
if ((flags & POSIX_SPAWN_SETSIGMASK) != 0)