Formerly hurd/hurd/signal.h.~13~
[kopensolaris-gnu/glibc.git] / hurd / hurd / signal.h
1 /* Implementing POSIX.1 signals under the Hurd.
2 Copyright (C) 1993, 1994 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 Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 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 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB.  If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA.  */
19
20 #ifndef _HURD_SIGNAL_H
21
22 #define _HURD_SIGNAL_H  1
23 #include <features.h>
24 /* Make sure <signal.h> is going to define NSIG.  */
25 #ifndef __USE_GNU
26 #error "Must have `_GNU_SOURCE' feature test macro to use this file"
27 #endif
28
29 #define __need_NULL
30 #include <stddef.h>
31
32 #include <mach/mach_types.h>
33 #include <mach/port.h>
34 #include <mach/message.h>
35 #include <hurd/hurd_types.h>
36 #include <signal.h>
37 #include <errno.h>
38
39 #include <mutex.h>
40 #include <lock-intern.h>
41
42
43 /* Per-thread signal state.  */
44
45 struct hurd_sigstate
46   {
47     /* XXX This should perhaps instead be something that identifies
48        cthreads multiplexed on a single kernel thread.  */
49     thread_t thread;
50     struct hurd_sigstate *next; /* Linked-list of thread sigstates.  */
51
52     struct mutex lock;          /* Locks the rest of this structure.  */
53     sigset_t blocked;
54     sigset_t pending;
55     struct sigaction actions[NSIG];
56     struct sigaltstack sigaltstack;
57     int sigcodes[NSIG];         /* Codes for pending signals.  */
58
59     int suspended;              /* If nonzero, sig_post signals `arrived'.  */
60 #ifdef noteven
61     struct condition arrived;
62 #endif
63
64 #if 0
65     int vforked;                /* Nonzero if this thread is a vfork child.  */
66     struct
67       {
68         process_t proc;
69         file_t ccdir, cwdir, crdir, auth;
70         mode_t umask;
71         int ctty_fstype;
72         fsid_t ctty_fsid;
73         ino_t ctty_fileid;
74         struct hurd_dtable *dtable;
75         jmp_buf continuation;
76       } *vfork_saved;
77 #endif
78
79     /* Not locked.  Used only by this thread,
80        or by signal thread with this thread suspended.  */
81     volatile mach_port_t intr_port; /* Port interruptible RPC was sent on.  */
82     volatile int intr_restart;  /* If nonzero, restart interrupted RPC.  */
83   };
84
85 /* Linked list of states of all threads whose state has been asked for.  */
86
87 extern struct hurd_sigstate *_hurd_sigstates;
88
89 extern struct mutex _hurd_siglock; /* Locks _hurd_sigstates.  */
90
91 /* Get the sigstate of a given thread, taking its lock.  */
92
93 extern struct hurd_sigstate *_hurd_thread_sigstate (thread_t);
94
95 /* Get the sigstate of the current thread, taking its lock.
96    This uses a per-thread variable to optimize the lookup.  */
97
98 #include <hurd/threadvar.h>
99 _EXTERN_INLINE struct hurd_sigstate *
100 _hurd_self_sigstate (void)
101 {
102   struct hurd_sigstate **location =
103     (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE);
104   if (*location)
105     __mutex_lock (&(*location)->lock);
106   else
107     *location = _hurd_thread_sigstate (__mach_thread_self ()); /* cproc_self */
108   return *location;
109 }
110 \f
111 /* Thread listening on our message port; also called the "signal thread".  */
112
113 extern thread_t _hurd_msgport_thread;
114
115 /* Our message port.  We hold the receive right and _hurd_msgport_thread
116    listens for messages on it.  We also hold a send right, for convenience.  */
117
118 extern mach_port_t _hurd_msgport;
119
120
121 /* Thread to receive process-global signals.  */
122
123 extern thread_t _hurd_sigthread;
124
125
126 /* Resource limit on core file size.  Enforced by hurdsig.c.  */
127 extern int _hurd_core_limit;
128 \f
129 /* Initialize the signal code, and start the signal thread.  */
130
131 extern void _hurdsig_init (void);
132
133 /* Initialize proc server-assisted fault recovery for the signal thread.  */
134
135 extern void _hurdsig_fault_init (void);
136
137 /* Raise a signal as described by SIGNO and SIGCODE, on the thread whose
138    sigstate SS points to.  If SS is a null pointer, this instead affects
139    the calling thread.  */
140
141 extern void _hurd_raise_signal (struct hurd_sigstate *ss,
142                                 int signo, int sigcode);
143
144 /* Translate a Mach exception into a signal (machine-dependent).  */
145
146 extern void _hurd_exception2signal (int exception, int code, int subcode,
147                                     int *signo, int *sigcode);
148
149
150 /* Make the thread described by SS take the signal described by SIGNO and
151    SIGCODE.  SS->lock is held on entry, and released before return.  */
152
153 extern void _hurd_internal_post_signal (struct hurd_sigstate *ss,
154                                         int signo, int sigcode);
155
156 /* Set up STATE to handle signal SIGNO by running HANDLER.  FLAGS is the
157    `sa_flags' member from `struct sigaction'.  If the SA_ONSTACK bit is
158    set, *ALTSTACK describes the alternate signal stack to use.  The handler
159    is passed SIGNO, SIGCODE, and the returned `struct sigcontext' (which
160    resides on the stack the handler will use, and which describes the state
161    of the thread encoded in STATE before running the handler).  */
162
163 extern struct sigcontext *_hurd_setup_sighandler (int flags,
164                                                   __sighandler_t handler,
165                                                   struct sigaltstack *altstack,
166                                                   int signo, int sigcode,
167                                                   void *state);
168
169 /* Function run by the signal thread to receive from the signal port.  */
170
171 extern void _hurd_msgport_receive (void);
172
173 /* Return nonzero if STATE indicates a thread that is blocked in a mach_msg
174    system call (machine-dependent).  If returning nonzero, set *PORT to
175    the receive right that the thread is blocked on.  */
176
177 extern int _hurd_thread_state_msging_p (void *state, mach_port_t *port);
178
179 /* Set up STATE with a thread state that, when resumed, is
180    like `longjmp (_hurd_sigthread_fault_env, 1)'.  */
181
182 extern void _hurd_initialize_fault_recovery_state (void *state);
183
184
185 /* Function run for SIGINFO when its action is SIG_DFL and the current
186    process is the session leader.  */
187
188 extern void _hurd_siginfo_handler (int);
189
190
191 #ifdef notyet
192
193 /* Perform interruptible RPC CALL on PORT.
194    The args in CALL should be constant or local variable refs.
195    They may be evaluated many times, and must not change.
196    PORT must not be deallocated before this RPC is finished.  */
197 #define HURD_EINTR_RPC(port, call) \
198   ({
199     error_t __err;
200     struct hurd_sigstate *__ss = _hurd_self_sigstate ();
201     __mutex_unlock (&__ss->lock); /* Lock not needed.  */
202     /* If we get a signal and should return EINTR, the signal thread will
203        clear this.  The RPC might return EINTR when some other thread gets
204        a signal, in which case we want to restart our call.  */
205     __ss->intr_restart = 1;
206     /* This one needs to be last.  A signal can arrive before here,
207        and if intr_port were set before intr_restart is
208        initialized, the signal thread would get confused.  */
209     __ss->intr_port = (port);
210     /* A signal may arrive here, after intr_port is set,
211        but before the mach_msg system call.  The signal handler might do an
212        interruptible RPC, and clobber intr_port; then it would not be set
213        properly when we actually did send the RPC, and a later signal
214        wouldn't interrupt that RPC.  So, _hurd_run_sighandler saves
215        intr_port in the sigcontext, and sigreturn restores it.  */
216   __do_call:
217     switch (__err = (call))
218       {
219       case EINTR:               /* RPC went out and was interrupted.  */
220       case MACH_SEND_INTERRUPTED: /* RPC didn't get out.  */
221         if (__ss->intr_restart)
222           /* Restart the interrupted call.  */
223           goto __do_call;
224         /* FALLTHROUGH */
225       case MACH_RCV_PORT_DIED:
226         /* Server didn't respond to interrupt_operation,
227            so the signal thread destroyed the reply port.  */
228         __err = EINTR;
229         break;
230       }
231     __ss->intr_port = MACH_PORT_NULL;
232     __err;
233   })
234
235 #endif /* notyet */
236
237 /* Mask of signals that cannot be caught, blocked, or ignored.  */
238 #define _SIG_CANT_MASK  (__sigmask (SIGSTOP) | __sigmask (SIGKILL))
239
240 /* Do an RPC to a process's message port.
241
242    Each argument is an expression which returns an error code; each
243    expression may be evaluated several times.  FETCH_MSGPORT_EXPR should
244    fetch the appropriate message port and store it in the local variable
245    `msgport'.  FETCH_REFPORT_EXPR should fetch the appropriate message port
246    and store it in the local variable `refport' (if no reference port is
247    needed in the call, then FETCH_REFPORT_EXPR should be simply
248    KERN_SUCCESS or 0).  Both of these are assumed to create user
249    references, which this macro deallocates.  RPC_EXPR should perform the
250    desired RPC operation using `msgport' and `refport'.
251
252    The reason for the complexity is that a process's message port and
253    reference port may change between fetching those ports and completing an
254    RPC using them (usually they change only when a process execs).  The RPC
255    will fail with MACH_SEND_INVALID_DEST if the msgport dies before we can
256    send the RPC request; or with MIG_SERVER_DIED if the msgport was
257    destroyed after we sent the RPC request but before it was serviced.  In
258    either of these cases, we retry the entire operation, discarding the old
259    message and reference ports and fetch them anew.  */
260
261 #define HURD_MSGPORT_RPC(fetch_msgport_expr, fetch_refport_expr, rpc_expr)   \
262 ({                                                                            \
263     error_t __err;                                                            \
264     mach_port_t msgport, refport = MACH_PORT_NULL;                            \
265     do                                                                        \
266       {                                                                       \
267         /* Get the message port.  */                                          \
268         if (__err = (fetch_msgport_expr))                                     \
269           break;                                                              \
270         /* Get the reference port.  */                                        \
271         if (__err = (fetch_refport_expr))                                     \
272           {                                                                   \
273             /* Couldn't get it; deallocate MSGPORT and fail.  */              \
274             __mach_port_deallocate (__mach_task_self (), msgport);            \
275             break;                                                            \
276           }                                                                   \
277         __err = (rpc_expr);                                                   \
278         __mach_port_deallocate (__mach_task_self (), msgport);                \
279         if (refport != MACH_PORT_NULL)                                        \
280           __mach_port_deallocate (__mach_task_self (), refport);              \
281       } while (__err != MACH_SEND_INVALID_DEST &&                             \
282                __err != MIG_SERVER_DIED);                                     \
283     __err;                                                                    \
284 })
285 \f
286 /* Some other parts of the library need to preempt signals, to detect
287    errors that should not result in a POSIX signal.  For example, when
288    some mapped region of memory is used, an extraneous SIGSEGV might be
289    generated when the mapping server returns an error for a page fault.  */
290
291 struct hurd_signal_preempt
292   {
293     /* Function to examine a thread receiving a given signal.  The handler
294        is called even for blocked signals.  This function is run in the
295        signal thread, with THREAD's sigstate locked; it should be as simple
296        and robust as possible.  THREAD is the thread which is about to
297        receive the signal.  SIGNO and SIGCODE would be passed to the normal
298        handler.
299
300        If the return value is SIG_DFL, normal signal processing continues.
301        If it is SIG_IGN, the signal is ignored.
302        Any other value is used in place of the normal handler.  */
303     sighandler_t (*handler) (thread_t thread, int signo, int sigcode);
304     int first, last;            /* Range of sigcodes this handler wants.  */
305     struct hurd_signal_preempt *next; /* Next handler on the chain. */
306   };
307
308 extern struct hurd_signal_preempt *_hurd_signal_preempt[NSIG];
309 extern struct mutex _hurd_signal_preempt_lock;
310
311
312 /* Initialize PREEMPTER with the information given and stick it in the
313    chain of preempters for SIGNO.  */
314
315 _EXTERN_INLINE int
316 hurd_preempt_signals (struct hurd_signal_preempt *preempter,
317                       int signo, int first_code, int last_code,
318                       sighandler_t (*handler) (thread_t, int, int))
319 {
320   if (signo <= 0 || signo >= NSIG)
321     {
322       errno = EINVAL;
323       return -1;
324     }
325   preempter->first = first_code;
326   preempter->last = last_code;
327   preempter->handler = handler;
328   __mutex_lock (&_hurd_signal_preempt_lock);
329   preempter->next = _hurd_signal_preempt[signo];
330   _hurd_signal_preempt[signo] = preempter;
331   __mutex_unlock (&_hurd_signal_preempt_lock);
332   return 0;
333 }
334
335 /* Remove PREEMPTER from the chain for SIGNO.  */
336
337 _EXTERN_INLINE int
338 hurd_unpreempt_signals (struct hurd_signal_preempt *preempter, int signo)
339 {
340   struct hurd_signal_preempt *p, *lastp;
341   if (signo <= 0 || signo >= NSIG)
342     {
343       errno = EINVAL;
344       return -1;
345     }
346   __mutex_lock (&_hurd_signal_preempt_lock);
347   for (p = _hurd_signal_preempt[signo], lastp = NULL;
348        p != NULL; lastp = p, p = p->next)
349     if (p == preempter)
350       {
351         (lastp == NULL ? _hurd_signal_preempt[signo] : lastp->next) = p->next;
352         __mutex_unlock (&_hurd_signal_preempt_lock);
353         return 0;
354       }
355   _hurd_signal_preempt[signo] = preempter;
356   __mutex_unlock (&_hurd_signal_preempt_lock);
357   errno = ENOENT;
358   return -1;
359 }
360
361
362 #endif  /* hurd/signal.h */