Back to index

glibc  2.9
signal.h
Go to the documentation of this file.
00001 /* Implementing POSIX.1 signals under the Hurd.
00002    Copyright (C) 1993,94,95,96,98,99,2002,2007,2008
00003        Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #ifndef       _HURD_SIGNAL_H
00022 
00023 #define       _HURD_SIGNAL_H       1
00024 #include <features.h>
00025 /* Make sure <signal.h> is going to define NSIG.  */
00026 #ifndef __USE_GNU
00027 #error "Must have `_GNU_SOURCE' feature test macro to use this file"
00028 #endif
00029 
00030 #define __need_size_t
00031 #define __need_NULL
00032 #include <stddef.h>
00033 
00034 #include <mach/mach_types.h>
00035 #include <mach/port.h>
00036 #include <mach/message.h>
00037 #include <hurd/hurd_types.h>
00038 #include <signal.h>
00039 #include <errno.h>
00040 #include <hurd/msg.h>
00041 
00042 #include <cthreads.h>              /* For `struct mutex'.  */
00043 #include <setjmp.h>         /* For `jmp_buf'.  */
00044 #include <spin-lock.h>
00045 #include <hurd/threadvar.h> /* We cache sigstate in a threadvar.  */
00046 struct hurd_signal_preemptor;      /* <hurd/sigpreempt.h> */
00047 
00048 
00049 /* Full details of a signal.  */
00050 struct hurd_signal_detail
00051   {
00052     /* Codes from origination Mach exception_raise message.  */
00053     integer_t exc, exc_code, exc_subcode;
00054     /* Sigcode as passed or computed from exception codes.  */
00055     integer_t code;
00056     /* Error code as passed or extracted from exception codes.  */
00057     error_t error;
00058   };
00059 
00060 
00061 /* Per-thread signal state.  */
00062 
00063 struct hurd_sigstate
00064   {
00065     spin_lock_t critical_section_lock; /* Held if in critical section.  */
00066 
00067     spin_lock_t lock;              /* Locks most of the rest of the structure.  */
00068 
00069     thread_t thread;
00070     struct hurd_sigstate *next; /* Linked-list of thread sigstates.  */
00071 
00072     sigset_t blocked;              /* What signals are blocked.  */
00073     sigset_t pending;              /* Pending signals, possibly blocked.  */
00074     struct sigaction actions[NSIG];
00075     struct sigaltstack sigaltstack;
00076 
00077     /* Chain of thread-local signal preemptors; see <hurd/sigpreempt.h>.
00078        Each element of this chain is in local stack storage, and the chain
00079        parallels the stack: the head of this chain is in the innermost
00080        stack frame, and each next element in an outermore frame.  */
00081     struct hurd_signal_preemptor *preemptors;
00082 
00083     /* For each signal that may be pending, the details to deliver it with.  */
00084     struct hurd_signal_detail pending_data[NSIG];
00085 
00086     /* If `suspended' is set when this thread gets a signal,
00087        the signal thread sends an empty message to it.  */
00088     mach_port_t suspended;
00089 
00090     /* The following members are not locked.  They are used only by this
00091        thread, or by the signal thread with this thread suspended.  */
00092 
00093     volatile mach_port_t intr_port; /* Port interruptible RPC was sent on.  */
00094 
00095     /* If this is not null, the thread is in sigreturn awaiting delivery of
00096        pending signals.  This context (the machine-dependent portions only)
00097        will be passed to sigreturn after running the handler for a pending
00098        signal, instead of examining the thread state.  */
00099     struct sigcontext *context;
00100 
00101     /* This is the head of the thread's list of active resources; see
00102        <hurd/userlink.h> for details.  This member is only used by the
00103        thread itself, and always inside a critical section.  */
00104     struct hurd_userlink *active_resources;
00105 
00106     /* These are locked normally.  */
00107     int cancel;                    /* Flag set by hurd_thread_cancel.  */
00108     void (*cancel_hook) (void);    /* Called on cancellation.  */
00109   };
00110 
00111 /* Linked list of states of all threads whose state has been asked for.  */
00112 
00113 extern struct hurd_sigstate *_hurd_sigstates;
00114 
00115 extern struct mutex _hurd_siglock; /* Locks _hurd_sigstates.  */
00116 
00117 /* Get the sigstate of a given thread, taking its lock.  */
00118 
00119 extern struct hurd_sigstate *_hurd_thread_sigstate (thread_t);
00120 
00121 /* Get the sigstate of the current thread.
00122    This uses a per-thread variable to optimize the lookup.  */
00123 
00124 extern struct hurd_sigstate *_hurd_self_sigstate (void)
00125      /* This declaration tells the compiler that the value is constant.
00126        We assume this won't be called twice from the same stack frame
00127        by different threads.  */
00128      __attribute__ ((__const__));
00129 
00130 #ifndef _HURD_SIGNAL_H_EXTERN_INLINE
00131 #define _HURD_SIGNAL_H_EXTERN_INLINE __extern_inline
00132 #endif
00133 
00134 _HURD_SIGNAL_H_EXTERN_INLINE struct hurd_sigstate *
00135 _hurd_self_sigstate (void)
00136 {
00137   struct hurd_sigstate **location =
00138     (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE);
00139   if (*location == NULL)
00140     *location = _hurd_thread_sigstate (__mach_thread_self ());
00141   return *location;
00142 }
00143 
00144 /* Thread listening on our message port; also called the "signal thread".  */
00145 
00146 extern thread_t _hurd_msgport_thread;
00147 
00148 /* Our message port.  We hold the receive right and _hurd_msgport_thread
00149    listens for messages on it.  We also hold a send right, for convenience.  */
00150 
00151 extern mach_port_t _hurd_msgport;
00152 
00153 
00154 /* Thread to receive process-global signals.  */
00155 
00156 extern thread_t _hurd_sigthread;
00157 
00158 
00159 /* Resource limit on core file size.  Enforced by hurdsig.c.  */
00160 extern int _hurd_core_limit;
00161 
00162 /* Critical sections.
00163 
00164    A critical section is a section of code which cannot safely be interrupted
00165    to run a signal handler; for example, code that holds any lock cannot be
00166    interrupted lest the signal handler try to take the same lock and
00167    deadlock result.  */
00168 
00169 _HURD_SIGNAL_H_EXTERN_INLINE void *
00170 _hurd_critical_section_lock (void)
00171 {
00172   struct hurd_sigstate **location =
00173     (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE);
00174   struct hurd_sigstate *ss = *location;
00175   if (ss == NULL)
00176     {
00177       /* The thread variable is unset; this must be the first time we've
00178         asked for it.  In this case, the critical section flag cannot
00179         possible already be set.  Look up our sigstate structure the slow
00180         way; this locks the sigstate lock.  */
00181       ss = *location = _hurd_thread_sigstate (__mach_thread_self ());
00182       __spin_unlock (&ss->lock);
00183     }
00184 
00185   if (! __spin_try_lock (&ss->critical_section_lock))
00186     /* We are already in a critical section, so do nothing.  */
00187     return NULL;
00188 
00189   /* With the critical section lock held no signal handler will run.
00190      Return our sigstate pointer; this will be passed to
00191      _hurd_critical_section_unlock to unlock it.  */
00192   return ss;
00193 }
00194 
00195 _HURD_SIGNAL_H_EXTERN_INLINE void
00196 _hurd_critical_section_unlock (void *our_lock)
00197 {
00198   if (our_lock == NULL)
00199     /* The critical section lock was held when we began.  Do nothing.  */
00200     return;
00201   else
00202     {
00203       /* It was us who acquired the critical section lock.  Unlock it.  */
00204       struct hurd_sigstate *ss = our_lock;
00205       sigset_t pending;
00206       __spin_lock (&ss->lock);
00207       __spin_unlock (&ss->critical_section_lock);
00208       pending = ss->pending & ~ss->blocked;
00209       __spin_unlock (&ss->lock);
00210       if (! __sigisemptyset (&pending))
00211        /* There are unblocked signals pending, which weren't
00212           delivered because we were in the critical section.
00213           Tell the signal thread to deliver them now.  */
00214        __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
00215     }
00216 }
00217 
00218 /* Convenient macros for simple uses of critical sections.
00219    These two must be used as a pair at the same C scoping level.  */
00220 
00221 #define HURD_CRITICAL_BEGIN \
00222   { void *__hurd_critical__ = _hurd_critical_section_lock ()
00223 #define HURD_CRITICAL_END \
00224       _hurd_critical_section_unlock (__hurd_critical__); } while (0)
00225 
00226 /* Initialize the signal code, and start the signal thread.
00227    Arguments give the "init ints" from exec_startup.  */
00228 
00229 extern void _hurdsig_init (const int *intarray, size_t intarraysize);
00230 
00231 /* Initialize proc server-assisted fault recovery for the signal thread.  */
00232 
00233 extern void _hurdsig_fault_init (void);
00234 
00235 /* Raise a signal as described by SIGNO an DETAIL, on the thread whose
00236    sigstate SS points to.  If SS is a null pointer, this instead affects
00237    the calling thread.  */
00238 
00239 extern void _hurd_raise_signal (struct hurd_sigstate *ss, int signo,
00240                             const struct hurd_signal_detail *detail);
00241 
00242 /* Translate a Mach exception into a signal (machine-dependent).  */
00243 
00244 extern void _hurd_exception2signal (struct hurd_signal_detail *detail,
00245                                 int *signo);
00246 
00247 
00248 /* Make the thread described by SS take the signal described by SIGNO and
00249    DETAIL.  If the process is traced, this will in fact stop with a SIGNO
00250    as the stop signal unless UNTRACED is nonzero.  When the signal can be
00251    considered delivered, sends a sig_post reply message on REPLY_PORT
00252    indicating success.  SS is not locked.  */
00253 
00254 extern void _hurd_internal_post_signal (struct hurd_sigstate *ss,
00255                                    int signo,
00256                                    struct hurd_signal_detail *detail,
00257                                    mach_port_t reply_port,
00258                                    mach_msg_type_name_t reply_port_type,
00259                                    int untraced);
00260 
00261 /* Set up STATE and SS to handle signal SIGNO by running HANDLER.  If
00262    RPC_WAIT is nonzero, the thread needs to wait for a pending RPC to
00263    finish before running the signal handler.  The handler is passed SIGNO,
00264    SIGCODE, and the returned `struct sigcontext' (which resides on the
00265    stack the handler will use, and which describes the state of the thread
00266    encoded in STATE before running the handler).  */
00267 
00268 struct machine_thread_all_state;
00269 extern struct sigcontext *
00270 _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
00271                      int signo, struct hurd_signal_detail *detail,
00272                      int rpc_wait, struct machine_thread_all_state *state);
00273 
00274 /* Function run by the signal thread to receive from the signal port.  */
00275 
00276 extern void _hurd_msgport_receive (void);
00277 
00278 /* Set up STATE with a thread state that, when resumed, is
00279    like `longjmp (_hurd_sigthread_fault_env, 1)'.  */
00280 
00281 extern void _hurd_initialize_fault_recovery_state (void *state);
00282 
00283 /* Set up STATE to do the equivalent of `longjmp (ENV, VAL);'.  */
00284 
00285 extern void _hurd_longjmp_thread_state (void *state, jmp_buf env, int value);
00286 
00287 /* Function run for SIGINFO when its action is SIG_DFL and the current
00288    process is the session leader.  */
00289 
00290 extern void _hurd_siginfo_handler (int);
00291 
00292 /* Replacement for mach_msg used in RPCs to provide Hurd interruption
00293    semantics.  Args are all the same as for mach_msg.  intr-rpc.h arranges
00294    for this version to be used automatically by the RPC stubs the library
00295    builds in place of the normal mach_msg. */
00296 error_t _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
00297                              mach_msg_option_t option,
00298                              mach_msg_size_t send_size,
00299                              mach_msg_size_t rcv_size,
00300                              mach_port_t rcv_name,
00301                              mach_msg_timeout_t timeout,
00302                              mach_port_t notify);
00303 
00304 
00305 /* Milliseconds to wait for an interruptible RPC to return after
00306    `interrupt_operation'.  */
00307 
00308 extern mach_msg_timeout_t _hurd_interrupted_rpc_timeout;
00309 
00310 
00311 /* Mask of signals that cannot be caught, blocked, or ignored.  */
00312 #define       _SIG_CANT_MASK       (__sigmask (SIGSTOP) | __sigmask (SIGKILL))
00313 
00314 /* Do an RPC to a process's message port.
00315 
00316    Each argument is an expression which returns an error code; each
00317    expression may be evaluated several times.  FETCH_MSGPORT_EXPR should
00318    fetch the appropriate message port and store it in the local variable
00319    `msgport'; it will be deallocated after use.  FETCH_REFPORT_EXPR should
00320    fetch the appropriate message port and store it in the local variable
00321    `refport' (if no reference port is needed in the call, then
00322    FETCH_REFPORT_EXPR should be simply KERN_SUCCESS or 0); if
00323    DEALLOC_REFPORT evaluates to nonzero it will be deallocated after use,
00324    otherwise the FETCH_REFPORT_EXPR must take care of user references to
00325    `refport'.  RPC_EXPR should perform the desired RPC operation using
00326    `msgport' and `refport'.
00327 
00328    The reason for the complexity is that a process's message port and
00329    reference port may change between fetching those ports and completing an
00330    RPC using them (usually they change only when a process execs).  The RPC
00331    will fail with MACH_SEND_INVALID_DEST if the msgport dies before we can
00332    send the RPC request; or with MIG_SERVER_DIED if the msgport was
00333    destroyed after we sent the RPC request but before it was serviced.  In
00334    either of these cases, we retry the entire operation, discarding the old
00335    message and reference ports and fetch them anew.  */
00336 
00337 #define HURD_MSGPORT_RPC(fetch_msgport_expr,                                \
00338                       fetch_refport_expr, dealloc_refport,                  \
00339                       rpc_expr)                                      \
00340 ({                                                                   \
00341     error_t __err;                                                   \
00342     mach_port_t msgport, refport = MACH_PORT_NULL;                          \
00343     do                                                               \
00344       {                                                                     \
00345        /* Get the message port.  */                                         \
00346        __err = (fetch_msgport_expr);                                        \
00347        if (__err)                                                    \
00348          break;                                                      \
00349        /* Get the reference port.  */                                       \
00350        __err = (fetch_refport_expr);                                        \
00351        if (__err)                                                    \
00352          {                                                           \
00353            /* Couldn't get it; deallocate MSGPORT and fail.  */             \
00354            __mach_port_deallocate (__mach_task_self (), msgport);           \
00355            break;                                                    \
00356          }                                                           \
00357        __err = (rpc_expr);                                           \
00358        __mach_port_deallocate (__mach_task_self (), msgport);               \
00359        if ((dealloc_refport) && refport != MACH_PORT_NULL)                  \
00360          __mach_port_deallocate (__mach_task_self (), refport);             \
00361       } while (__err == MACH_SEND_INVALID_DEST ||                           \
00362               __err == MIG_SERVER_DIED);                             \
00363     __err;                                                           \
00364 })
00365 
00366 
00367 #endif /* hurd/signal.h */