]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - hurd/hurdsig.c
Break lines before not after operators, batch 4.
[thirdparty/glibc.git] / hurd / hurdsig.c
index 2507a8b8a98014265efdd319f2830411fced9a8c..1b511d1e8f9932322862c573b3a4c903c22c5f9e 100644 (file)
@@ -1,5 +1,4 @@
-/* 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>
@@ -31,6 +31,9 @@
 
 #include "hurdfault.h"
 #include "hurdmalloc.h"                /* XXX */
+#include "../locale/localeinfo.h"
+
+#include <libc-diag.h>
 
 const char *_hurdsig_getenv (const char *);
 
@@ -49,13 +52,12 @@ thread_t _hurd_sigthread;
 /* 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])
@@ -90,6 +92,7 @@ _hurd_thread_sigstate (thread_t thread)
       __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;
@@ -121,6 +124,7 @@ _hurd_thread_sigstate (thread_t thread)
   __mutex_unlock (&_hurd_siglock);
   return ss;
 }
+libc_hidden_def (_hurd_thread_sigstate)
 \f
 /* Signal delivery itself is on this page.  */
 
@@ -131,7 +135,7 @@ _hurd_thread_sigstate (thread_t thread)
 #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>
@@ -235,18 +239,24 @@ abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state,
    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 ();
@@ -255,7 +265,7 @@ interrupted_reply_port_location (struct machine_thread_all_state *thread_state,
 }
 \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;
@@ -283,6 +293,7 @@ _hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
                     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;
@@ -298,7 +309,8 @@ _hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
      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
@@ -309,11 +321,11 @@ _hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
       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
@@ -324,7 +336,8 @@ _hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
           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);
 
@@ -449,8 +462,8 @@ sigset_t _hurdsig_preempted_set;
 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
@@ -525,8 +538,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
       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);
@@ -702,9 +715,9 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
        }
     }
 
-  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
@@ -715,9 +728,9 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
     }
 
   /* 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;
@@ -742,6 +755,11 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
       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. */
@@ -758,6 +776,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
         Nothing to do but die; BSD gets SIGILL in this case.  */
       detail->code = signo;    /* XXX ? */
       signo = SIGILL;
+
+    fatal:
       act = core;
       /* FALLTHROUGH */
 
@@ -829,7 +849,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
 
            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
@@ -895,7 +916,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
        {
          /* 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)
            {
@@ -1009,7 +1031,7 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
                      || 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);
@@ -1126,6 +1148,7 @@ signal_allowed (int signo, mach_port_t refport)
              }
            _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;
@@ -1248,7 +1271,8 @@ _hurdsig_init (const int *intarray, size_t intarraysize)
 
   /* 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);
@@ -1259,12 +1283,10 @@ _hurdsig_init (const int *intarray, size_t intarraysize)
                                 (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.  */
@@ -1284,9 +1306,25 @@ _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.  */
-#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).
@@ -1330,23 +1368,23 @@ reauth_proc (mach_port_t new)
   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.  */
 }