-/* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
+/* Copyright (C) 1991,92,93,94,95,96,97,98,99,2000,2001,2002,2005,2008
+ 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
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
-#include <stdlib.h>
#include <stdio.h>
-#include <hurd.h>
-#include <hurd/signal.h>
-#include <cthreads.h> /* For `struct mutex'. */
+#include <stdlib.h>
#include <string.h>
+
+#include <cthreads.h> /* For `struct mutex'. */
+#include <mach.h>
+#include <mach/thread_switch.h>
+
+#include <hurd.h>
#include <hurd/id.h>
+#include <hurd/signal.h>
+
#include "hurdfault.h"
#include "hurdmalloc.h" /* XXX */
+#include "../locale/localeinfo.h"
const char *_hurdsig_getenv (const char *);
__sigemptyset (&ss->pending);
memset (&ss->sigaltstack, 0, sizeof (ss->sigaltstack));
ss->preemptors = NULL;
- ss->suspended = 0;
+ ss->suspended = MACH_PORT_NULL;
ss->intr_port = MACH_PORT_NULL;
ss->context = NULL;
#include <hurd/fd.h>
#include <hurd/crash.h>
+#include <hurd/resource.h>
#include <hurd/paths.h>
#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>
#include <assert.h>
#include <unistd.h>
-int _hurd_core_limit; /* XXX */
/* Call the crash dump server to mummify us before we die.
Returns nonzero if a core file was written. */
file_t file, coredir;
const char *name;
+ /* Don't bother locking since we just read the one word. */
+ rlim_t corelimit = _hurd_rlimits[RLIMIT_CORE].rlim_cur;
+
+ if (corelimit == 0)
+ /* No core dumping, thank you very much. Note that this makes
+ `ulimit -c 0' prevent crash-suspension too, which is probably
+ what the user wanted. */
+ return 0;
+
/* XXX RLIMIT_CORE:
When we have a protocol to make the server return an error
for RLIMIT_FSIZE, then tell the corefile fs server the RLIMIT_CORE
if (! err && file != MACH_PORT_NULL)
/* The core dump into FILE succeeded, so now link it into the
directory. */
- err = __dir_link (file, coredir, name, 1);
+ err = __dir_link (coredir, file, name, 1);
__mach_port_deallocate (__mach_task_self (), file);
__mach_port_deallocate (__mach_task_self (), coredir);
return !err && file != MACH_PORT_NULL;
}
\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;
handler = ss->preemptors ? try_preemptor (ss->preemptors) : SIG_ERR;
/* If no thread-specific preemptor, check for a global one. */
- if (handler == SIG_ERR && (__sigmask (signo) & _hurdsig_preempted_set))
+ if (handler == SIG_ERR && __sigismember (&_hurdsig_preempted_set, signo))
{
__mutex_lock (&_hurd_siglock);
handler = try_preemptor (_hurdsig_preemptors);
if (__sigmask (signo) & STOPSIGS)
/* Stop signals clear a pending SIGCONT even if they
are handled or ignored (but not if preempted). */
- ss->pending &= ~sigmask (SIGCONT);
+ __sigdelset (&ss->pending, SIGCONT);
else
{
if (signo == SIGCONT)
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 */
/* Backdoor extra argument to signal handler. */
scp->sc_error = detail->error;
- /* Block SIGNO and requested signals while running the handler. */
+ /* Block requested signals while running the handler. */
scp->sc_mask = ss->blocked;
- ss->blocked |= __sigmask (signo) | ss->actions[signo].sa_mask;
+ __sigorset (&ss->blocked, &ss->blocked, &ss->actions[signo].sa_mask);
+
+ /* Also block SIGNO unless we're asked not to. */
+ if (! (ss->actions[signo].sa_flags & (SA_RESETHAND | SA_NODEFER)))
+ __sigaddset (&ss->blocked, signo);
+
+ /* Reset to SIG_DFL if requested. SIGILL and SIGTRAP cannot
+ be automatically reset when delivered; the system silently
+ enforces this restriction. */
+ if (ss->actions[signo].sa_flags & SA_RESETHAND
+ && signo != SIGILL && signo != SIGTRAP)
+ ss->actions[signo].sa_handler = SIG_DFL;
/* Start the thread running the handler (or possibly waiting for an
RPC reply before running the handler). */
/* There is a sigsuspend waiting. Tell it to wake up. */
error_t err;
mach_msg_header_t msg;
- err = __mach_port_insert_right (__mach_task_self (),
- ss->suspended, ss->suspended,
- MACH_MSG_TYPE_MAKE_SEND);
- assert_perror (err);
- msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MOVE_SEND, 0);
+ 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. */
- msg.msgh_seqno = 17; /* Random. */
ss->suspended = MACH_PORT_NULL;
err = __mach_msg (&msg, MACH_SEND_MSG, sizeof msg, 0,
MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
}
_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;
if (intarraysize > INIT_SIGMASK)
ss->blocked = intarray[INIT_SIGMASK];
if (intarraysize > INIT_SIGPENDING)
- ss->blocked = intarray[INIT_SIGPENDING];
+ ss->pending = intarray[INIT_SIGPENDING];
if (intarraysize > INIT_SIGIGN && intarray[INIT_SIGIGN] != 0)
{
int signo;
err = __thread_create (__mach_task_self (), &_hurd_msgport_thread);
assert_perror (err);
- stacksize = ~__hurd_threadvar_stack_mask + 1;
stacksize = __vm_page_size * 8; /* Small stack for signal thread. */
err = __mach_setup_thread (__mach_task_self (), _hurd_msgport_thread,
_hurd_msgport_receive,
malloc (__hurd_threadvar_max * sizeof (unsigned long int));
if (__hurd_sigthread_variables == NULL)
__libc_fatal ("hurd: Can't allocate threadvars for signal thread\n");
+ memset (__hurd_sigthread_variables, 0,
+ __hurd_threadvar_max * sizeof (unsigned long int));
+ __hurd_sigthread_variables[_HURD_THREADVAR_LOCALE]
+ = (unsigned long int) &_nl_global_locale;
/* Reinitialize the MiG support routines so they will use a per-thread
variable for the cached reply port. */
#pragma weak cthread_fork
#pragma weak cthread_detach
cthread_detach (cthread_fork ((cthread_fn_t) &_hurd_msgport_receive, 0));
+
+ /* XXX We need the thread port for the signal thread further on
+ in this thread (see hurdfault.c:_hurdsigfault_init).
+ Therefore we block until _hurd_msgport_thread is initialized
+ by the newly created thread. This really shouldn't be
+ necessary; we should be able to fetch the thread port for a
+ cthread from here. */
+ while (_hurd_msgport_thread == 0)
+ __swtch_pri (0);
}
/* Receive exceptions on the signal port. */
+#ifdef TASK_EXCEPTION_PORT
__task_set_special_port (__mach_task_self (),
TASK_EXCEPTION_PORT, _hurd_msgport);
+#elif defined (EXC_MASK_ALL)
+ __task_set_exception_ports (__mach_task_self (),
+ EXC_MASK_ALL & ~(EXC_MASK_SYSCALL
+ | EXC_MASK_MACH_SYSCALL
+ | EXC_MASK_RPC_ALERT),
+ _hurd_msgport,
+ EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
+#else
+# error task_set_exception_port?
+#endif
/* Sanity check. Any pending, unblocked signals should have been
taken by our predecessor incarnation (i.e. parent or pre-exec state)
const char *
_hurdsig_getenv (const char *variable)
{
+ if (__libc_enable_secure)
+ return NULL;
+
if (_hurdsig_catch_memory_fault (__environ))
/* We bombed in getenv. */
return NULL;
_hurdsig_fault_preemptor.last = VM_MAX_ADDRESS;
if (! strncmp (p, variable, len) && p[len] == '=')
{
- char *value;
size_t valuelen;
p += len + 1;
valuelen = strlen (p);