-/* Copyright (C) 1991,92,93,94,95,96,97,98,99,2000,01
- Free Software Foundation, Inc.
+/* Copyright (C) 1991-2019 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cthreads.h> /* For `struct mutex'. */
+#include <pthreadP.h>
#include <mach.h>
#include <mach/thread_switch.h>
+#include <mach/mig_support.h>
#include <hurd.h>
#include <hurd/id.h>
#include "hurdfault.h"
#include "hurdmalloc.h" /* XXX */
+#include "../locale/localeinfo.h"
+
+#include <libc-diag.h>
const char *_hurdsig_getenv (const char *);
/* These are set up by _hurdsig_init. */
unsigned long int __hurd_sigthread_stack_base;
unsigned long int __hurd_sigthread_stack_end;
-unsigned long int *__hurd_sigthread_variables;
/* Linked-list of per-thread signal state. */
struct hurd_sigstate *_hurd_sigstates;
/* Timeout for RPC's after interrupt_operation. */
-mach_msg_timeout_t _hurd_interrupted_rpc_timeout = 3000;
+mach_msg_timeout_t _hurd_interrupted_rpc_timeout = 60000;
\f
static void
default_sigaction (struct sigaction actions[NSIG])
__sigemptyset (&ss->blocked);
__sigemptyset (&ss->pending);
memset (&ss->sigaltstack, 0, sizeof (ss->sigaltstack));
+ ss->sigaltstack.ss_flags |= SS_DISABLE;
ss->preemptors = NULL;
ss->suspended = MACH_PORT_NULL;
ss->intr_port = MACH_PORT_NULL;
__mutex_unlock (&_hurd_siglock);
return ss;
}
+libc_hidden_def (_hurd_thread_sigstate)
\f
/* Signal delivery itself is on this page. */
#include <setjmp.h>
#include <fcntl.h>
#include <sys/wait.h>
-#include "thread_state.h"
+#include <thread_state.h>
#include <hurd/msg_server.h>
#include <hurd/msg_reply.h> /* For __msg_sig_post_reply. */
#include <hurd/interrupt.h>
that this location can be set without faulting, or else return NULL. */
static mach_port_t *
-interrupted_reply_port_location (struct machine_thread_all_state *thread_state,
+interrupted_reply_port_location (thread_t thread,
+ struct machine_thread_all_state *thread_state,
int sigthread)
{
- mach_port_t *portloc = (mach_port_t *) __hurd_threadvar_location_from_sp
- (_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->basic.SP);
+ mach_port_t *portloc = &THREAD_TCB(thread, thread_state)->reply_port;
if (sigthread && _hurdsig_catch_memory_fault (portloc))
- /* Faulted trying to read the stack. */
+ /* 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 ();
}
\f
#include <hurd/sigpreempt.h>
-#include "intr-msg.h"
+#include <intr-msg.h>
/* Timeout on interrupt_operation calls. */
mach_msg_timeout_t _hurdsig_interrupt_timeout = 1000;
struct machine_thread_all_state *state, int *state_change,
void (*reply) (void))
{
+ extern const void _hurd_intr_rpc_msg_about_to;
extern const void _hurd_intr_rpc_msg_in_trap;
mach_port_t rcv_port = MACH_PORT_NULL;
mach_port_t intr_port;
receive completes immediately or aborts. */
abort_thread (ss, state, reply);
- if (state->basic.PC < (natural_t) &_hurd_intr_rpc_msg_in_trap)
+ if (state->basic.PC >= (natural_t) &_hurd_intr_rpc_msg_about_to
+ && state->basic.PC < (natural_t) &_hurd_intr_rpc_msg_in_trap)
{
/* The thread is about to do the RPC, but hasn't yet entered
mach_msg. Mutate the thread's state so it knows not to try
state->basic.SYSRETURN = MACH_SEND_INTERRUPTED;
*state_change = 1;
}
- else if (state->basic.PC == (natural_t) &_hurd_intr_rpc_msg_in_trap &&
+ else if (state->basic.PC == (natural_t) &_hurd_intr_rpc_msg_in_trap
/* The thread was blocked in the system call. After thread_abort,
the return value register indicates what state the RPC was in
when interrupted. */
- state->basic.SYSRETURN == MACH_RCV_INTERRUPTED)
+ && state->basic.SYSRETURN == MACH_RCV_INTERRUPTED)
{
/* The RPC request message was sent and the thread was waiting for
the reply message; now the message receive has been aborted, so
our nonzero return tells the trampoline code to finish the message
receive operation before running the handler. */
- mach_port_t *reply = interrupted_reply_port_location (state,
+ mach_port_t *reply = interrupted_reply_port_location (ss->thread,
+ state,
sigthread);
error_t err = __interrupt_operation (intr_port, _hurdsig_interrupt_timeout);
weak_alias (_hurdsig_preemptors, _hurdsig_preempters)
/* Mask of stop signals. */
-#define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) | \
- sigmask (SIGSTOP) | sigmask (SIGTSTP))
+#define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) \
+ | sigmask (SIGSTOP) | sigmask (SIGTSTP))
/* Deliver a signal. SS is not locked. */
void
assert_perror (err);
for (i = 0; i < nthreads; ++i)
{
- if (threads[i] != _hurd_msgport_thread &&
- (act != handle || threads[i] != ss->thread))
+ if (threads[i] != _hurd_msgport_thread
+ && (act != handle || threads[i] != ss->thread))
{
err = __thread_resume (threads[i]);
assert_perror (err);
}
}
- if (_hurd_orphaned && act == stop &&
- (__sigmask (signo) & (__sigmask (SIGTTIN) | __sigmask (SIGTTOU) |
- __sigmask (SIGTSTP))))
+ if (_hurd_orphaned && act == stop
+ && (__sigmask (signo) & (__sigmask (SIGTTIN) | __sigmask (SIGTTOU)
+ | __sigmask (SIGTSTP))))
{
/* If we would ordinarily stop for a job control signal, but we are
orphaned so noone would ever notice and continue us again, we just
}
/* Handle receipt of a blocked signal, or any signal while stopped. */
- if (act != ignore && /* Signals ignored now are forgotten now. */
- __sigismember (&ss->blocked, signo) ||
- (signo != SIGKILL && _hurd_stopped))
+ if (act != ignore /* Signals ignored now are forgotten now. */
+ && __sigismember (&ss->blocked, signo)
+ || (signo != SIGKILL && _hurd_stopped))
{
mark_pending ();
act = ignore;
break;
case ignore:
+ if (detail->exc)
+ /* Blocking or ignoring a machine exception is fatal.
+ Otherwise we could just spin on the faulting instruction. */
+ goto fatal;
+
/* Nobody cares about this signal. If there was a call to resume
above in SIGCONT processing and we've left a thread suspended,
now's the time to set it going. */
Nothing to do but die; BSD gets SIGILL in this case. */
detail->code = signo; /* XXX ? */
signo = SIGILL;
+
+ fatal:
act = core;
/* FALLTHROUGH */
if (! machine_get_basic_state (ss->thread, &thread_state))
goto sigbomb;
- loc = interrupted_reply_port_location (&thread_state, 1);
+ loc = interrupted_reply_port_location (ss->thread,
+ &thread_state, 1);
if (loc && *loc != MACH_PORT_NULL)
/* This is the reply port for the context which called
sigreturn. Since we are abandoning that context entirely
{
/* Fetch the thread variable for the MiG reply port,
and set it to MACH_PORT_NULL. */
- mach_port_t *loc = interrupted_reply_port_location (&thread_state,
+ mach_port_t *loc = interrupted_reply_port_location (ss->thread,
+ &thread_state,
1);
if (loc)
{
|| ss->actions[signo].sa_handler == SIG_IGN
|| ss->actions[signo].sa_handler == SIG_DFL))
{
- mutex_unlock (&_hurd_siglock);
+ __mutex_unlock (&_hurd_siglock);
goto deliver_pending;
}
__spin_unlock (&ss->lock);
}
_hurd_port_free (&_hurd_dtable[d]->port, &ulink, port);
}
+ __mutex_unlock (&_hurd_dtable_lock);
/* If we found a lucky winner, we've set D to -1 in the loop. */
if (lucky)
goto win;
/* Start the signal thread listening on the message port. */
- if (__hurd_threadvar_stack_mask == 0)
+#pragma weak __cthread_fork
+ if (!__cthread_fork)
{
err = __thread_create (__mach_task_self (), &_hurd_msgport_thread);
assert_perror (err);
(vm_address_t *) &__hurd_sigthread_stack_base,
&stacksize);
assert_perror (err);
+ err = __mach_setup_tls (_hurd_msgport_thread);
+ assert_perror (err);
__hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
- __hurd_sigthread_variables =
- malloc (__hurd_threadvar_max * sizeof (unsigned long int));
- if (__hurd_sigthread_variables == NULL)
- __libc_fatal ("hurd: Can't allocate threadvars for signal thread\n");
/* Reinitialize the MiG support routines so they will use a per-thread
variable for the cached reply port. */
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. */
-#pragma weak cthread_fork
-#pragma weak cthread_detach
- cthread_detach (cthread_fork ((cthread_fn_t) &_hurd_msgport_receive, 0));
+#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 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);
+ __hurd_sigthread_stack_base = (uintptr_t) addr;
+ __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + size;
+ }
/* XXX We need the thread port for the signal thread further on
in this thread (see hurdfault.c:_hurdsigfault_init).
ref = __mach_reply_port ();
if (! HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
__proc_reauthenticate (port, ref,
- MACH_MSG_TYPE_MAKE_SEND) ||
- __auth_user_authenticate (new, ref,
- MACH_MSG_TYPE_MAKE_SEND,
- &ignore))
+ MACH_MSG_TYPE_MAKE_SEND)
+ || __auth_user_authenticate (new, ref,
+ MACH_MSG_TYPE_MAKE_SEND,
+ &ignore))
&& ignore != MACH_PORT_NULL)
__mach_port_deallocate (__mach_task_self (), ignore);
__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. */
}