(linenum→info "unix/slp.c:2238")

glibc/2.7/hurd/hurdsig.c

    1: /* Copyright (C) 1991,92,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2005
    2:         Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4: 
    5:    The GNU C Library is free software; you can redistribute it and/or
    6:    modify it under the terms of the GNU Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the License, or (at your option) any later version.
    9: 
   10:    The GNU C Library is distributed in the hope that it will be useful,
   11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include <stdio.h>
   21: #include <stdlib.h>
   22: #include <string.h>
   23: 
   24: #include <cthreads.h>           /* For `struct mutex'.  */
   25: #include <mach.h>
   26: #include <mach/thread_switch.h>
   27: 
   28: #include <hurd.h>
   29: #include <hurd/id.h>
   30: #include <hurd/signal.h>
   31: 
   32: #include "hurdfault.h"
   33: #include "hurdmalloc.h"         /* XXX */
   34: #include "../locale/localeinfo.h"
   35: 
   36: const char *_hurdsig_getenv (const char *);
   37: 
   38: struct mutex _hurd_siglock;
   39: int _hurd_stopped;
   40: 
   41: /* Port that receives signals and other miscellaneous messages.  */
   42: mach_port_t _hurd_msgport;
   43: 
   44: /* Thread listening on it.  */
   45: thread_t _hurd_msgport_thread;
   46: 
   47: /* Thread which receives task-global signals.  */
   48: thread_t _hurd_sigthread;
   49: 
   50: /* These are set up by _hurdsig_init.  */
   51: unsigned long int __hurd_sigthread_stack_base;
   52: unsigned long int __hurd_sigthread_stack_end;
   53: unsigned long int *__hurd_sigthread_variables;
   54: 
   55: /* Linked-list of per-thread signal state.  */
   56: struct hurd_sigstate *_hurd_sigstates;
   57: 
   58: /* Timeout for RPC's after interrupt_operation. */
   59: mach_msg_timeout_t _hurd_interrupted_rpc_timeout = 3000;
   60: ^L
   61: static void
   62: default_sigaction (struct sigaction actions[NSIG])
   63: {
   64:   int signo;
   65: 
   66:   __sigemptyset (&actions[0].sa_mask);
   67:   actions[0].sa_flags = SA_RESTART;
   68:   actions[0].sa_handler = SIG_DFL;
   69: 
   70:   for (signo = 1; signo < NSIG; ++signo)
   71:     actions[signo] = actions[0];
   72: }
   73: 
   74: struct hurd_sigstate *
   75: _hurd_thread_sigstate (thread_t thread)
   76: {
   77:   struct hurd_sigstate *ss;
   78:   __mutex_lock (&_hurd_siglock);
   79:   for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
   80:     if (ss->thread == thread)
   81:        break;
   82:   if (ss == NULL)
   83:     {
   84:       ss = malloc (sizeof (*ss));
   85:       if (ss == NULL)
   86:         __libc_fatal ("hurd: Can't allocate thread sigstate\n");
   87:       ss->thread = thread;
   88:       __spin_lock_init (&ss->lock);
   89: 
   90:       /* Initialize default state.  */
   91:       __sigemptyset (&ss->blocked);
   92:       __sigemptyset (&ss->pending);
   93:       memset (&ss->sigaltstack, 0, sizeof (ss->sigaltstack));
   94:       ss->preemptors = NULL;
   95:       ss->suspended = MACH_PORT_NULL;
   96:       ss->intr_port = MACH_PORT_NULL;
   97:       ss->context = NULL;
   98: 
   99:       /* Initialize the sigaction vector from the default signal receiving
  100:          thread's state, and its from the system defaults.  */
  101:       if (thread == _hurd_sigthread)
  102:         default_sigaction (ss->actions);
  103:       else
  104:         {
  105:           struct hurd_sigstate *s;
  106:           for (s = _hurd_sigstates; s != NULL; s = s->next)
  107:             if (s->thread == _hurd_sigthread)
  108:               break;
  109:           if (s)
  110:             {
  111:               __spin_lock (&s->lock);
  112:               memcpy (ss->actions, s->actions, sizeof (s->actions));
  113:               __spin_unlock (&s->lock);
  114:             }
  115:           else
  116:             default_sigaction (ss->actions);
  117:         }
  118: 
  119:       ss->next = _hurd_sigstates;
  120:       _hurd_sigstates = ss;
  121:     }
  122:   __mutex_unlock (&_hurd_siglock);
  123:   return ss;
  124: }
  125: ^L
  126: /* Signal delivery itself is on this page.  */
  127: 
  128: #include <hurd/fd.h>
  129: #include <hurd/crash.h>
  130: #include <hurd/resource.h>
  131: #include <hurd/paths.h>
  132: #include <setjmp.h>
  133: #include <fcntl.h>
  134: #include <sys/wait.h>
  135: #include <thread_state.h>
  136: #include <hurd/msg_server.h>
  137: #include <hurd/msg_reply.h>     /* For __msg_sig_post_reply.  */
  138: #include <hurd/interrupt.h>
  139: #include <assert.h>
  140: #include <unistd.h>
  141: 
  142: 
  143: /* Call the crash dump server to mummify us before we die.
  144:    Returns nonzero if a core file was written.  */
  145: static int
  146: write_corefile (int signo, const struct hurd_signal_detail *detail)
  147: {
  148:   error_t err;
  149:   mach_port_t coreserver;
  150:   file_t file, coredir;
  151:   const char *name;
  152: 
  153:   /* Don't bother locking since we just read the one word.  */
  154:   rlim_t corelimit = _hurd_rlimits[RLIMIT_CORE].rlim_cur;
  155: 
  156:   if (corelimit == 0)
  157:     /* No core dumping, thank you very much.  Note that this makes
  158:        `ulimit -c 0' prevent crash-suspension too, which is probably
  159:        what the user wanted.  */
  160:     return 0;
  161: 
  162:   /* XXX RLIMIT_CORE:
  163:      When we have a protocol to make the server return an error
  164:      for RLIMIT_FSIZE, then tell the corefile fs server the RLIMIT_CORE
  165:      value in place of the RLIMIT_FSIZE value.  */
  166: 
  167:   /* First get a port to the core dumping server.  */
  168:   coreserver = MACH_PORT_NULL;
  169:   name = _hurdsig_getenv ("CRASHSERVER");
  170:   if (name != NULL)
  171:     coreserver = __file_name_lookup (name, 0, 0);
  172:   if (coreserver == MACH_PORT_NULL)
  173:     coreserver = __file_name_lookup (_SERVERS_CRASH, 0, 0);
  174:   if (coreserver == MACH_PORT_NULL)
  175:     return 0;
  176: 
  177:   /* Get a port to the directory where the new core file will reside.  */
  178:   file = MACH_PORT_NULL;
  179:   name = _hurdsig_getenv ("COREFILE");
  180:   if (name == NULL)
  181:     name = "core";
  182:   coredir = __file_name_split (name, (char **) &name);
  183:   if (coredir != MACH_PORT_NULL)
  184:     /* Create the new file, but don't link it into the directory yet.  */
  185:     __dir_mkfile (coredir, O_WRONLY|O_CREAT,
  186:                   0600 & ~_hurd_umask, /* XXX ? */
  187:                   &file);
  188: 
  189:   /* Call the core dumping server to write the core file.  */
  190:   err = __crash_dump_task (coreserver,
  191:                            __mach_task_self (),
  192:                            file,
  193:                            signo, detail->code, detail->error,
  194:                            detail->exc, detail->exc_code, detail->exc_subcode,
  195:                            _hurd_ports[INIT_PORT_CTTYID].port,
  196:                            MACH_MSG_TYPE_COPY_SEND);
  197:   __mach_port_deallocate (__mach_task_self (), coreserver);
  198: 
  199:   if (! err && file != MACH_PORT_NULL)
  200:     /* The core dump into FILE succeeded, so now link it into the
  201:        directory.  */
  202:     err = __dir_link (coredir, file, name, 1);
  203:   __mach_port_deallocate (__mach_task_self (), file);
  204:   __mach_port_deallocate (__mach_task_self (), coredir);
  205:   return !err && file != MACH_PORT_NULL;
  206: }
  207: 
  208: 
  209: /* The lowest-numbered thread state flavor value is 1,
  210:    so we use bit 0 in machine_thread_all_state.set to
  211:    record whether we have done thread_abort.  */
  212: #define THREAD_ABORTED 1
  213: 
  214: /* SS->thread is suspended.  Abort the thread and get its basic state.  */
  215: static void
  216: abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state,
  217:               void (*reply) (void))
  218: {
  219:   if (!(state->set & THREAD_ABORTED))
  220:     {
  221:       error_t err = __thread_abort (ss->thread);
  222:       assert_perror (err);
  223:       /* Clear all thread state flavor set bits, because thread_abort may
  224:          have changed the state.  */
  225:       state->set = THREAD_ABORTED;
  226:     }
  227: 
  228:   if (reply)
  229:     (*reply) ();
  230: 
  231:   machine_get_basic_state (ss->thread, state);
  232: }
  233: 
  234: /* Find the location of the MiG reply port cell in use by the thread whose
  235:    state is described by THREAD_STATE.  If SIGTHREAD is nonzero, make sure
  236:    that this location can be set without faulting, or else return NULL.  */
  237: 
  238: static mach_port_t *
  239: interrupted_reply_port_location (struct machine_thread_all_state *thread_state,
  240:                                  int sigthread)
  241: {
  242:   mach_port_t *portloc = (mach_port_t *) __hurd_threadvar_location_from_sp
  243:     (_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->basic.SP);
  244: 
  245:   if (sigthread && _hurdsig_catch_memory_fault (portloc))
  246:     /* Faulted trying to read the stack.  */
  247:     return NULL;
  248: 
  249:   /* Fault now if this pointer is bogus.  */
  250:   *(volatile mach_port_t *) portloc = *portloc;
  251: 
  252:   if (sigthread)
  253:     _hurdsig_end_catch_fault ();
  254: 
  255:   return portloc;
  256: }
  257: ^L
  258: #include <hurd/sigpreempt.h>
  259: #include <intr-msg.h>
  260: 
  261: /* Timeout on interrupt_operation calls.  */
  262: mach_msg_timeout_t _hurdsig_interrupt_timeout = 1000;
  263: 
  264: /* SS->thread is suspended.
  265: 
  266:    Abort any interruptible RPC operation the thread is doing.
  267: 
  268:    This uses only the constant member SS->thread and the unlocked, atomically
  269:    set member SS->intr_port, so no locking is needed.
  270: 
  271:    If successfully sent an interrupt_operation and therefore the thread should
  272:    wait for its pending RPC to return (possibly EINTR) before taking the
  273:    incoming signal, returns the reply port to be received on.  Otherwise
  274:    returns MACH_PORT_NULL.
  275: 
  276:    SIGNO is used to find the applicable SA_RESTART bit.  If SIGNO is zero,
  277:    the RPC fails with EINTR instead of restarting (thread_cancel).
  278: 
  279:    *STATE_CHANGE is set nonzero if STATE->basic was modified and should
  280:    be applied back to the thread if it might ever run again, else zero.  */
  281: 
  282: mach_port_t
  283: _hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
  284:                      struct machine_thread_all_state *state, int *state_change,
  285:                      void (*reply) (void))
  286: {
  287:   extern const void _hurd_intr_rpc_msg_in_trap;
  288:   mach_port_t rcv_port = MACH_PORT_NULL;
  289:   mach_port_t intr_port;
  290: 
  291:   *state_change = 0;
  292: 
  293:   intr_port = ss->intr_port;
  294:   if (intr_port == MACH_PORT_NULL)
  295:     /* No interruption needs done.  */
  296:     return MACH_PORT_NULL;
  297: 
  298:   /* Abort the thread's kernel context, so any pending message send or
  299:      receive completes immediately or aborts.  */
  300:   abort_thread (ss, state, reply);
  301: 
  302:   if (state->basic.PC < (natural_t) &_hurd_intr_rpc_msg_in_trap)
  303:     {
  304:       /* The thread is about to do the RPC, but hasn't yet entered
  305:          mach_msg.  Mutate the thread's state so it knows not to try
  306:          the RPC.  */
  307:       INTR_MSG_BACK_OUT (&state->basic);
  308:       MACHINE_THREAD_STATE_SET_PC (&state->basic,
  309:                                    &_hurd_intr_rpc_msg_in_trap);
  310:       state->basic.SYSRETURN = MACH_SEND_INTERRUPTED;
  311:       *state_change = 1;
  312:     }
  313:   else if (state->basic.PC == (natural_t) &_hurd_intr_rpc_msg_in_trap &&
  314:            /* The thread was blocked in the system call.  After thread_abort,
  315:               the return value register indicates what state the RPC was in
  316:               when interrupted.  */
  317:            state->basic.SYSRETURN == MACH_RCV_INTERRUPTED)
  318:       {
  319:         /* The RPC request message was sent and the thread was waiting for
  320:            the reply message; now the message receive has been aborted, so
  321:            the mach_msg call will return MACH_RCV_INTERRUPTED.  We must tell
  322:            the server to interrupt the pending operation.  The thread must
  323:            wait for the reply message before running the signal handler (to
  324:            guarantee that the operation has finished being interrupted), so
  325:            our nonzero return tells the trampoline code to finish the message
  326:            receive operation before running the handler.  */
  327: 
  328:         mach_port_t *reply = interrupted_reply_port_location (state,
  329:                                                               sigthread);
  330:         error_t err = __interrupt_operation (intr_port, _hurdsig_interrupt_timeout);
  331: 
  332:         if (err)
  333:           {
  334:             if (reply)
  335:               {
  336:                 /* The interrupt didn't work.
  337:                    Destroy the receive right the thread is blocked on.  */
  338:                 __mach_port_destroy (__mach_task_self (), *reply);
  339:                 *reply = MACH_PORT_NULL;
  340:               }
  341: 
  342:             /* The system call return value register now contains
  343:                MACH_RCV_INTERRUPTED; when mach_msg resumes, it will retry the
  344:                call.  Since we have just destroyed the receive right, the
  345:                retry will fail with MACH_RCV_INVALID_NAME.  Instead, just
  346:                change the return value here to EINTR so mach_msg will not
  347:                retry and the EINTR error code will propagate up.  */
  348:             state->basic.SYSRETURN = EINTR;
  349:             *state_change = 1;
  350:           }
  351:         else if (reply)
  352:           rcv_port = *reply;
  353: 
  354:         /* All threads whose RPCs were interrupted by the interrupt_operation
  355:            call above will retry their RPCs unless we clear SS->intr_port.
  356:            So we clear it for the thread taking a signal when SA_RESTART is
  357:            clear, so that its call returns EINTR.  */
  358:         if (! signo || !(ss->actions[signo].sa_flags & SA_RESTART))
  359:           ss->intr_port = MACH_PORT_NULL;
  360:       }
  361: 
  362:   return rcv_port;
  363: }
  364: 
  365: 
  366: /* Abort the RPCs being run by all threads but this one;
  367:    all other threads should be suspended.  If LIVE is nonzero, those
  368:    threads may run again, so they should be adjusted as necessary to be
  369:    happy when resumed.  STATE is clobbered as a scratch area; its initial
  370:    contents are ignored, and its contents on return are not useful.  */
  371: 
  372: static void
  373: abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live)
  374: {
  375:   /* We can just loop over the sigstates.  Any thread doing something
  376:      interruptible must have one.  We needn't bother locking because all
  377:      other threads are stopped.  */
  378: 
  379:   struct hurd_sigstate *ss;
  380:   size_t nthreads;
  381:   mach_port_t *reply_ports;
  382: 
  383:   /* First loop over the sigstates to count them.
  384:      We need to know how big a vector we will need for REPLY_PORTS.  */
  385:   nthreads = 0;
  386:   for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
  387:     ++nthreads;
  388: 
  389:   reply_ports = alloca (nthreads * sizeof *reply_ports);
  390: 
  391:   nthreads = 0;
  392:   for (ss = _hurd_sigstates; ss != NULL; ss = ss->next, ++nthreads)
  393:     if (ss->thread == _hurd_msgport_thread)
  394:       reply_ports[nthreads] = MACH_PORT_NULL;
  395:     else
  396:       {
  397:         int state_changed;
  398:         state->set = 0;                /* Reset scratch area.  */
  399: 
  400:         /* Abort any operation in progress with interrupt_operation.
  401:            Record the reply port the thread is waiting on.
  402:            We will wait for all the replies below.  */
  403:         reply_ports[nthreads] = _hurdsig_abort_rpcs (ss, signo, 1,
  404:                                                      state, &state_changed,
  405:                                                      NULL);
  406:         if (live)
  407:           {
  408:             if (reply_ports[nthreads] != MACH_PORT_NULL)
  409:               {
  410:                 /* We will wait for the reply to this RPC below, so the
  411:                    thread must issue a new RPC rather than waiting for the
  412:                    reply to the one it sent.  */
  413:                 state->basic.SYSRETURN = EINTR;
  414:                 state_changed = 1;
  415:               }
  416:             if (state_changed)
  417:               /* Aborting the RPC needed to change this thread's state,
  418:                  and it might ever run again.  So write back its state.  */
  419:               __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
  420:                                   (natural_t *) &state->basic,
  421:                                   MACHINE_THREAD_STATE_COUNT);
  422:           }
  423:       }
  424: 
  425:   /* Wait for replies from all the successfully interrupted RPCs.  */
  426:   while (nthreads-- > 0)
  427:     if (reply_ports[nthreads] != MACH_PORT_NULL)
  428:       {
  429:         error_t err;
  430:         mach_msg_header_t head;
  431:         err = __mach_msg (&head, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, sizeof head,
  432:                           reply_ports[nthreads],
  433:                           _hurd_interrupted_rpc_timeout, MACH_PORT_NULL);
  434:         switch (err)
  435:           {
  436:           case MACH_RCV_TIMED_OUT:
  437:           case MACH_RCV_TOO_LARGE:
  438:             break;
  439: 
  440:           default:
  441:             assert_perror (err);
  442:           }
  443:       }
  444: }
  445: 
  446: struct hurd_signal_preemptor *_hurdsig_preemptors = 0;
  447: sigset_t _hurdsig_preempted_set;
  448: 
  449: /* XXX temporary to deal with spelling fix */
  450: weak_alias (_hurdsig_preemptors, _hurdsig_preempters)
  451: 
  452: /* Mask of stop signals.  */
  453: #define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) | \
  454:                   sigmask (SIGSTOP) | sigmask (SIGTSTP))
  455: 
  456: /* Deliver a signal.  SS is not locked.  */
  457: void
  458: _hurd_internal_post_signal (struct hurd_sigstate *ss,
  459:                             int signo, struct hurd_signal_detail *detail,
  460:                             mach_port_t reply_port,
  461:                             mach_msg_type_name_t reply_port_type,
  462:                             int untraced)
  463: {
  464:   error_t err;
  465:   struct machine_thread_all_state thread_state;
  466:   enum { stop, ignore, core, term, handle } act;
  467:   sighandler_t handler;
  468:   sigset_t pending;
  469:   int ss_suspended;
  470: 
  471:   /* Reply to this sig_post message.  */
  472:   __typeof (__msg_sig_post_reply) *reply_rpc
  473:     = (untraced ? __msg_sig_post_untraced_reply : __msg_sig_post_reply);
  474:   void reply (void)
  475:     {
  476:       error_t err;
  477:       if (reply_port == MACH_PORT_NULL)
  478:         return;
  479:       err = (*reply_rpc) (reply_port, reply_port_type, 0);
  480:       reply_port = MACH_PORT_NULL;
  481:       if (err != MACH_SEND_INVALID_DEST) /* Ignore dead reply port.  */
  482:         assert_perror (err);
  483:     }
  484: 
  485:   /* Mark the signal as pending.  */
  486:   void mark_pending (void)
  487:     {
  488:       __sigaddset (&ss->pending, signo);
  489:       /* Save the details to be given to the handler when SIGNO is
  490:          unblocked.  */
  491:       ss->pending_data[signo] = *detail;
  492:     }
  493: 
  494:   /* Suspend the process with SIGNO.  */
  495:   void suspend (void)
  496:     {
  497:       /* Stop all other threads and mark ourselves stopped.  */
  498:       __USEPORT (PROC,
  499:                  ({
  500:                    /* Hold the siglock while stopping other threads to be
  501:                       sure it is not held by another thread afterwards.  */
  502:                    __mutex_lock (&_hurd_siglock);
  503:                    __proc_dostop (port, _hurd_msgport_thread);
  504:                    __mutex_unlock (&_hurd_siglock);
  505:                    abort_all_rpcs (signo, &thread_state, 1);
  506:                    reply ();
  507:                    __proc_mark_stop (port, signo, detail->code);
  508:                  }));
  509:       _hurd_stopped = 1;
  510:     }
  511:   /* Resume the process after a suspension.  */
  512:   void resume (void)
  513:     {
  514:       /* Resume the process from being stopped.  */
  515:       thread_t *threads;
  516:       mach_msg_type_number_t nthreads, i;
  517:       error_t err;
  518: 
  519:       if (! _hurd_stopped)
  520:         return;
  521: 
  522:       /* Tell the proc server we are continuing.  */
  523:       __USEPORT (PROC, __proc_mark_cont (port));
  524:       /* Fetch ports to all our threads and resume them.  */
  525:       err = __task_threads (__mach_task_self (), &threads, &nthreads);
  526:       assert_perror (err);
  527:       for (i = 0; i < nthreads; ++i)
  528:         {
  529:           if (threads[i] != _hurd_msgport_thread &&
  530:               (act != handle || threads[i] != ss->thread))
  531:             {
  532:               err = __thread_resume (threads[i]);
  533:               assert_perror (err);
  534:             }
  535:           err = __mach_port_deallocate (__mach_task_self (),
  536:                                         threads[i]);
  537:           assert_perror (err);
  538:         }
  539:       __vm_deallocate (__mach_task_self (),
  540:                        (vm_address_t) threads,
  541:                        nthreads * sizeof *threads);
  542:       _hurd_stopped = 0;
  543:       if (act == handle)
  544:         /* The thread that will run the handler is already suspended.  */
  545:         ss_suspended = 1;
  546:     }
  547: 
  548:   if (signo == 0)
  549:     {
  550:       if (untraced)
  551:         /* This is PTRACE_CONTINUE.  */
  552:         resume ();
  553: 
  554:       /* This call is just to check for pending signals.  */
  555:       __spin_lock (&ss->lock);
  556:       goto check_pending_signals;
  557:     }
  558: 
  559:  post_signal:
  560: 
  561:   thread_state.set = 0;         /* We know nothing.  */
  562: 
  563:   __spin_lock (&ss->lock);
  564: 
  565:   /* Check for a preempted signal.  Preempted signals can arrive during
  566:      critical sections.  */
  567:   {
  568:     inline sighandler_t try_preemptor (struct hurd_signal_preemptor *pe)
  569:       {                         /* PE cannot be null.  */
  570:         do
  571:           {
  572:             if (HURD_PREEMPT_SIGNAL_P (pe, signo, detail->code))
  573:               {
  574:                 if (pe->preemptor)
  575:                   {
  576:                     sighandler_t handler = (*pe->preemptor) (pe, ss,
  577:                                                              &signo, detail);
  578:                     if (handler != SIG_ERR)
  579:                       return handler;
  580:                   }
  581:                 else
  582:                   return pe->handler;
  583:               }
  584:             pe = pe->next;
  585:           } while (pe != 0);
  586:         return SIG_ERR;
  587:       }
  588: 
  589:     handler = ss->preemptors ? try_preemptor (<