aboutsummaryrefslogtreecommitdiff
path: root/hurd/hurdsig.c
diff options
context:
space:
mode:
Diffstat (limited to 'hurd/hurdsig.c')
-rw-r--r--hurd/hurdsig.c112
1 files changed, 65 insertions, 47 deletions
diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c
index 7affb906d5..68be2e9bd0 100644
--- a/hurd/hurdsig.c
+++ b/hurd/hurdsig.c
@@ -265,11 +265,14 @@ interrupted_reply_port_location (struct machine_thread_all_state *thread_state,
incoming signal, returns the reply port to be received on. Otherwise
returns MACH_PORT_NULL.
+ SIGNO is used to find the applicable SA_RESTART bit. If SIGNO is zero,
+ the RPC fails with EINTR instead of restarting (thread_cancel).
+
*STATE_CHANGE is set nonzero if STATE->basic was modified and should
be applied back to the thread if it might ever run again, else zero. */
mach_port_t
-_hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
+_hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
struct machine_thread_all_state *state, int *state_change,
mach_port_t *reply_port,
mach_msg_type_name_t reply_port_type,
@@ -480,6 +483,52 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
}));
_hurd_stopped = 1;
}
+ /* Resume the process after a suspension. */
+ void resume (void)
+ {
+ /* Resume the process from being stopped. */
+ thread_t *threads;
+ mach_msg_type_number_t nthreads, i;
+ error_t err;
+
+ if (! _hurd_stopped)
+ return;
+
+ /* Tell the proc server we are continuing. */
+ __USEPORT (PROC, __proc_mark_cont (port));
+ /* Fetch ports to all our threads and resume them. */
+ err = __task_threads (__mach_task_self (), &threads, &nthreads);
+ assert_perror (err);
+ for (i = 0; i < nthreads; ++i)
+ {
+ if (threads[i] != _hurd_msgport_thread &&
+ (act != handle || threads[i] != ss->thread))
+ {
+ err = __thread_resume (threads[i]);
+ assert_perror (err);
+ }
+ err = __mach_port_deallocate (__mach_task_self (),
+ threads[i]);
+ assert_perror (err);
+ }
+ __vm_deallocate (__mach_task_self (),
+ (vm_address_t) threads,
+ nthreads * sizeof *threads);
+ _hurd_stopped = 0;
+ /* The thread that will run the handler is already suspended. */
+ ss_suspended = 1;
+ }
+
+ if (signo == 0)
+ {
+ if (untraced)
+ /* This is PTRACE_CONTINUE. */
+ resume ();
+
+ /* This call is just to check for pending signals. */
+ __spin_lock (&ss->lock);
+ goto check_pending_signals;
+ }
post_signal:
@@ -514,8 +563,6 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
__spin_lock (&ss->lock);
- handler = ss->actions[signo].sa_handler;
-
if (!untraced && (_hurd_exec_flags & EXEC_TRACED))
{
/* We are being traced. Stop to tell the debugger of the signal. */
@@ -530,6 +577,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
return;
}
+ handler = ss->actions[signo].sa_handler;
+
if (handler == SIG_DFL)
/* Figure out the default action for this signal. */
switch (signo)
@@ -604,35 +653,7 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
ss->pending &= ~STOPSIGS;
if (_hurd_stopped && act != stop && (untraced || signo == SIGCONT))
- {
- /* Resume the process from being stopped. */
- thread_t *threads;
- mach_msg_type_number_t nthreads, i;
- error_t err;
- /* Tell the proc server we are continuing. */
- __USEPORT (PROC, __proc_mark_cont (port));
- /* Fetch ports to all our threads and resume them. */
- err = __task_threads (__mach_task_self (), &threads, &nthreads);
- assert_perror (err);
- for (i = 0; i < nthreads; ++i)
- {
- if (threads[i] != _hurd_msgport_thread &&
- (act != handle || threads[i] != ss->thread))
- {
- err = __thread_resume (threads[i]);
- assert_perror (err);
- }
- err = __mach_port_deallocate (__mach_task_self (),
- threads[i]);
- assert_perror (err);
- }
- __vm_deallocate (__mach_task_self (),
- (vm_address_t) threads,
- nthreads * sizeof *threads);
- _hurd_stopped = 0;
- /* The thread that will run the handler is already suspended. */
- ss_suspended = 1;
- }
+ resume ();
}
}
@@ -648,10 +669,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
act = term;
}
- /* Handle receipt of a blocked signal, or any signal while stopped.
- It matters that we test ACT first here, because we must never pass
- SIGNO==0 to __sigismember. */
- if ((act != ignore && __sigismember (&ss->blocked, signo)) ||
+ /* Handle receipt of a blocked signal, or any signal while stopped. */
+ if (__sigismember (&ss->blocked, signo) ||
(signo != SIGKILL && _hurd_stopped))
{
mark_pending ();
@@ -754,7 +773,7 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
ss->context = &ocontext;
}
_hurdsig_end_catch_fault ();
-
+
if (! machine_get_basic_state (ss->thread, &thread_state))
goto sigbomb;
loc = interrupted_reply_port_location (&thread_state, 1);
@@ -772,7 +791,7 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
else
{
wait_for_reply
- = (_hurdsig_abort_rpcs (ss, signo, 1,
+ = (_hurdsig_abort_rpcs (ss, signo, 1,
&thread_state, &state_changed,
&reply_port, reply_port_type, untraced)
!= MACH_PORT_NULL);
@@ -851,12 +870,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
}
/* The signal has either been ignored or is now being handled. We can
- consider it delivered and reply to the killer. The exception is
- signal 0, which can be sent by a user thread to make us check for
- pending signals. In that case we want to deliver the pending signals
- before replying. */
- if (signo != 0)
- reply ();
+ consider it delivered and reply to the killer. */
+ reply ();
/* We get here unless the signal was fatal. We still hold SS->lock.
Check for pending signals, and loop to post them. */
@@ -874,6 +889,9 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
return pending = ss->pending & ~ss->blocked;
}
+ check_pending_signals:
+ untraced = 0;
+
if (signals_pending ())
{
pending:
@@ -974,7 +992,7 @@ signal_allowed (int signo, mach_port_t refport)
/* A continue signal can be sent by anyone in the session. */
mach_port_t sessport;
if (! __USEPORT (PROC, __proc_getsidport (port, &sessport)))
- {
+ {
__mach_port_deallocate (__mach_task_self (), sessport);
if (refport == sessport)
goto win;
@@ -1099,7 +1117,7 @@ _hurdsig_init (void)
MACH_PORT_RIGHT_RECEIVE,
&_hurd_msgport))
__libc_fatal ("hurd: Can't create message port receive right\n");
-
+
/* Make a send right to the signal port. */
if (err = __mach_port_insert_right (__mach_task_self (),
_hurd_msgport,
@@ -1135,7 +1153,7 @@ _hurdsig_init (void)
if (err = __thread_resume (_hurd_msgport_thread))
__libc_fatal ("hurd: Can't resume signal thread\n");
-
+
#if 0 /* Don't confuse poor gdb. */
/* Receive exceptions on the signal port. */
__task_set_special_port (__mach_task_self (),