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

glibc/2.7/hurd/hurdfault.c

    1: /* Handle faults in the signal thread.
    2:    Copyright (C) 1994,1995,1996,1997,2002,2005
    3:         Free Software Foundation, Inc.
    4:    This file is part of the GNU C Library.
    5: 
    6:    The GNU C Library is free software; you can redistribute it and/or
    7:    modify it under the terms of the GNU Lesser General Public
    8:    License as published by the Free Software Foundation; either
    9:    version 2.1 of the License, or (at your option) any later version.
   10: 
   11:    The GNU C Library is distributed in the hope that it will be useful,
   12:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   13:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:    Lesser General Public License for more details.
   15: 
   16:    You should have received a copy of the GNU Lesser General Public
   17:    License along with the GNU C Library; if not, write to the Free
   18:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   19:    02111-1307 USA.  */
   20: 
   21: #include <hurd.h>
   22: #include <hurd/signal.h>
   23: #include "hurdfault.h"
   24: #include <errno.h>
   25: #include <string.h>
   26: #include <setjmp.h>
   27: #include <stdio.h>
   28: #include <thread_state.h>
   29: #include "faultexc_server.h"    /* mig-generated header for our exc server.  */
   30: #include <assert.h>
   31: 
   32: jmp_buf _hurdsig_fault_env;
   33: struct hurd_signal_preemptor _hurdsig_fault_preemptor = {0};
   34: 
   35: /* XXX temporary to deal with spelling fix */
   36: weak_alias (_hurdsig_fault_preemptor, _hurdsig_fault_preempter)
   37: 
   38: static mach_port_t forward_sigexc;
   39: 
   40: kern_return_t
   41: _hurdsig_fault_catch_exception_raise (mach_port_t port,
   42:                                       thread_t thread,
   43:                                       task_t task,
   44: #ifdef EXC_MASK_ALL             /* New interface flavor.  */
   45:                                       exception_type_t exception,
   46:                                       exception_data_t code,
   47:                                       mach_msg_type_number_t codeCnt
   48: #else                           /* Vanilla Mach 3.0 interface.  */
   49:                                       integer_t exception,
   50:                                       integer_t code, integer_t subcode
   51: #endif
   52:                                       )
   53: {
   54:   int signo;
   55:   struct hurd_signal_detail d;
   56: 
   57:   if (port != forward_sigexc ||
   58:       thread != _hurd_msgport_thread || task != __mach_task_self ())
   59:     return EPERM;               /* Strange bogosity.  */
   60: 
   61:   d.exc = exception;
   62: #ifdef EXC_MASK_ALL
   63:   assert (codeCnt >= 2);
   64:   d.exc_code = code[0];
   65:   d.exc_subcode = code[1];
   66: #else
   67:   d.exc_code = code;
   68:   d.exc_subcode = subcode;
   69: #endif
   70: 
   71:   /* Call the machine-dependent function to translate the Mach exception
   72:      codes into a signal number and subcode.  */
   73:   _hurd_exception2signal (&d, &signo);
   74: 
   75:   return HURD_PREEMPT_SIGNAL_P (&_hurdsig_fault_preemptor, signo, d.code)
   76:     ? 0 : EGREGIOUS;
   77: }
   78: 
   79: #ifdef EXC_MASK_ALL
   80: /* XXX New interface flavor has additional RPCs that we could be using
   81:    instead.  These RPCs roll a thread_get_state/thread_set_state into
   82:    the message, so the signal thread ought to use these to save some calls.
   83:  */
   84: kern_return_t
   85: _hurdsig_fault_catch_exception_raise_state
   86: (mach_port_t port,
   87:  exception_type_t exception,
   88:  exception_data_t code,
   89:  mach_msg_type_number_t codeCnt,
   90:  int *flavor,
   91:  thread_state_t old_state,
   92:  mach_msg_type_number_t old_stateCnt,
   93:  thread_state_t new_state,
   94:  mach_msg_type_number_t *new_stateCnt)
   95: {
   96:   abort ();
   97:   return KERN_FAILURE;
   98: }
   99: 
  100: kern_return_t
  101: _hurdsig_fault_catch_exception_raise_state_identity
  102: (mach_port_t exception_port,
  103:  thread_t thread,
  104:  task_t task,
  105:  exception_type_t exception,
  106:  exception_data_t code,
  107:  mach_msg_type_number_t codeCnt,
  108:  int *flavor,
  109:  thread_state_t old_state,
  110:  mach_msg_type_number_t old_stateCnt,
  111:  thread_state_t new_state,
  112:  mach_msg_type_number_t *new_stateCnt)
  113: {
  114:   abort ();
  115:   return KERN_FAILURE;
  116: }
  117: #endif
  118: 
  119: 
  120: #ifdef NDR_CHAR_ASCII           /* OSF Mach flavors have different names.  */
  121: # define mig_reply_header_t     mig_reply_error_t
  122: #endif
  123: 
  124: static void
  125: faulted (void)
  126: {
  127:   struct
  128:     {
  129:       mach_msg_header_t head;
  130:       char buf[64];
  131:     } request;
  132:   mig_reply_header_t reply;
  133:   extern int _hurdsig_fault_exc_server (mach_msg_header_t *,
  134:                                         mach_msg_header_t *);
  135: 
  136:  /* Wait for the exception_raise message forwarded by the proc server.  */
  137: 
  138:  if (__mach_msg (&request.head, MACH_RCV_MSG, 0,
  139:                   sizeof request, forward_sigexc,
  140:                   MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL)
  141:       != MACH_MSG_SUCCESS)
  142:     __libc_fatal ("msg receive failed on signal thread exc\n");
  143: 
  144:   /* Run the exc demuxer which should call the server function above.
  145:      That function returns 0 if the exception was expected.  */
  146:   _hurdsig_fault_exc_server (&request.head, &reply.Head);
  147:   if (reply.Head.msgh_remote_port != MACH_PORT_NULL)
  148:     __mach_msg (&reply.Head, MACH_SEND_MSG, reply.Head.msgh_size,
  149:                 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
  150:   if (reply.RetCode == MIG_BAD_ID)
  151:     __mach_msg_destroy (&request.head);
  152: 
  153:   if (reply.RetCode)
  154:     __libc_fatal ("BUG: unexpected fault in signal thread\n");
  155: 
  156:   _hurdsig_fault_preemptor.signals = 0;
  157:   longjmp (_hurdsig_fault_env, 1);
  158: }
  159: 
  160: static char faultstack[1024];
  161: 
  162: /* Send exceptions for the signal thread to the proc server.
  163:    It will forward the message on to our message port,
  164:    and then restore the thread's state to code which
  165:    does `longjmp (_hurd_sigthread_fault_env, 1)'.  */
  166: 
  167: void
  168: _hurdsig_fault_init (void)
  169: {
  170:   error_t err;
  171:   struct machine_thread_state state;
  172:   mach_port_t sigexc;
  173: 
  174:   /* Allocate a port to receive signal thread exceptions.
  175:      We will move this receive right to the proc server.  */
  176:   err = __mach_port_allocate (__mach_task_self (),
  177:                               MACH_PORT_RIGHT_RECEIVE, &sigexc);
  178:   assert_perror (err);
  179:   err = __mach_port_allocate (__mach_task_self (),
  180:                               MACH_PORT_RIGHT_RECEIVE, &forward_sigexc);
  181:   assert_perror (err);
  182: 
  183:   /* Allocate a port to receive the exception msgs forwarded
  184:      from the proc server.  */
  185:   err = __mach_port_insert_right (__mach_task_self (), sigexc,
  186:                                   sigexc, MACH_MSG_TYPE_MAKE_SEND);
  187:   assert_perror (err);
  188: 
  189:   /* Set the queue limit for this port to just one.  The proc server will
  190:      notice if we ever get a second exception while one remains queued and
  191:      unreceived, and decide we are hopelessly buggy.  */
  192: #ifdef MACH_PORT_RECEIVE_STATUS_COUNT
  193:   {
  194:     const mach_port_limits_t lim = { mpl_qlimit: 1 };
  195:     assert (MACH_PORT_RECEIVE_STATUS_COUNT == sizeof lim / sizeof (natural_t));
  196:     err = __mach_port_set_attributes (__mach_task_self (), forward_sigexc,
  197:                                       MACH_PORT_RECEIVE_STATUS,
  198:                                       (mach_port_info_t) &lim,
  199:                                       MACH_PORT_RECEIVE_STATUS_COUNT);
  200:   }
  201: #else
  202:   err = __mach_port_set_qlimit (__mach_task_self (), forward_sigexc, 1);
  203: #endif
  204:   assert_perror (err);
  205: 
  206:   /* This state will be restored when we fault.
  207:      It runs the function above.  */
  208:   memset (&state, 0, sizeof state);
  209:   MACHINE_THREAD_STATE_SET_PC (&state, faulted);
  210:   MACHINE_THREAD_STATE_SET_SP (&state, faultstack, sizeof faultstack);
  211: 
  212:   err = __USEPORT
  213:     (PROC,
  214:      __proc_handle_exceptions (port,
  215:                                sigexc,
  216:                                forward_sigexc, MACH_MSG_TYPE_MAKE_SEND,
  217:                                MACHINE_THREAD_STATE_FLAVOR,
  218:                                (natural_t *) &state,
  219:                                MACHINE_THREAD_STATE_COUNT));
  220:   assert_perror (err);
  221: 
  222:   /* Direct signal thread exceptions to the proc server.  */
  223: #ifdef THREAD_EXCEPTION_PORT
  224:   err = __thread_set_special_port (_hurd_msgport_thread,
  225:                                    THREAD_EXCEPTION_PORT, sigexc);
  226: #elif defined (EXC_MASK_ALL)
  227:   __thread_set_exception_ports (_hurd_msgport_thread,
  228:                                 EXC_MASK_ALL & ~(EXC_MASK_SYSCALL
  229:                                                  | EXC_MASK_MACH_SYSCALL
  230:                                                  | EXC_MASK_RPC_ALERT),
  231:                                 sigexc,
  232:                                 EXCEPTION_STATE_IDENTITY,
  233:                                 MACHINE_THREAD_STATE);
  234: #else
  235: # error thread_set_exception_ports?
  236: #endif
  237:   __mach_port_deallocate (__mach_task_self (), sigexc);
  238:   assert_perror (err);
  239: }
Syntax (Markdown)