📄 signal.h
字号:
extern thread_t _hurd_sigthread;/* Resource limit on core file size. Enforced by hurdsig.c. */extern int _hurd_core_limit;/* Initialize the signal code, and start the signal thread. */extern void _hurdsig_init (void);/* Initialize proc server-assisted fault recovery for the signal thread. */extern void _hurdsig_fault_init (void);/* Raise a signal as described by SIGNO, SIGCODE and SIGERROR, on the thread whose sigstate SS points to. If SS is a null pointer, this instead affects the calling thread. */extern void _hurd_raise_signal (struct hurd_sigstate *ss, int signo, int sigcode, int sigerror);/* Translate a Mach exception into a signal (machine-dependent). */extern void _hurd_exception2signal (int exception, int code, int subcode, int *signo, int *sigcode, int *error);/* Make the thread described by SS take the signal described by SIGNO and SIGCODE. When the signal can be considered delivered, sends a sig_post reply message on REPLY_PORT indicating success. SS->lock is held on entry, and released before return. */extern void _hurd_internal_post_signal (struct hurd_sigstate *ss, int signo, int sigcode, int error, mach_port_t reply_port, mach_msg_type_name_t reply_port_type);/* Set up STATE and SS to handle signal SIGNO by running HANDLER. If RPC_WAIT is nonzero, the thread needs to wait for a pending RPC to finish before running the signal handler. The handler is passed SIGNO, SIGCODE, and the returned `struct sigcontext' (which resides on the stack the handler will use, and which describes the state of the thread encoded in STATE before running the handler). */struct machine_thread_all_state;extern struct sigcontext *_hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, int signo, int sigcode, int rpc_wait, struct machine_thread_all_state *state);/* Function run by the signal thread to receive from the signal port. */extern void _hurd_msgport_receive (void);/* STATE describes a thread that had intr_port set (meaning it was inside HURD_EINTR_RPC), after it has been thread_abort'd. It it looks to have just completed a mach_msg_trap system call that returned MACH_RCV_INTERRUPTED, return nonzero and set *PORT to the receive right being waited on. */extern int _hurdsig_rcv_interrupted_p (struct machine_thread_all_state *state, mach_port_t *port);/* Set up STATE with a thread state that, when resumed, is like `longjmp (_hurd_sigthread_fault_env, 1)'. */extern void _hurd_initialize_fault_recovery_state (void *state);/* Function run for SIGINFO when its action is SIG_DFL and the current process is the session leader. */extern void _hurd_siginfo_handler (int);/* Perform interruptible RPC CALL on PORT. The call should use The args in CALL should be constant or local variable refs. They may be evaluated many times, and must not change. PORT must not be deallocated before this RPC is finished. */#define HURD_EINTR_RPC(port, call) \ ({ \ __label__ __do_call; /* Give this label block scope. */ \ error_t __err; \ struct hurd_sigstate *__ss = _hurd_self_sigstate_unlocked (); \ __do_call: \ /* Tell the signal thread that we are doing an interruptible RPC on \ this port. If we get a signal and should return EINTR, the signal \ thread will set this variable to MACH_PORT_NULL. The RPC might \ return EINTR when some other thread gets a signal, in which case we \ want to restart our call. */ \ __ss->intr_port = (port); \ /* A signal may arrive here, after intr_port is set, but before the \ mach_msg system call. The signal handler might do an interruptible \ RPC, and clobber intr_port; then it would not be set properly when \ we actually did send the RPC, and a later signal wouldn't interrupt \ that RPC. So, _hurd_setup_sighandler saves intr_port in the \ sigcontext, and sigreturn restores it. */ \ switch (__err = (call)) \ { \ case EINTR: /* RPC went out and was interrupted. */ \ case MACH_SEND_INTERRUPTED: /* RPC didn't get out. */ \ if (__ss->intr_port != MACH_PORT_NULL) \ /* If this signal was for us and it should interrupt calls, the \ signal thread will have cleared SS->intr_port. Since it's not \ cleared, the signal was for another thread, or SA_RESTART is \ set. Restart the interrupted call. */ \ goto __do_call; \ /* FALLTHROUGH */ \ case MACH_RCV_PORT_DIED: \ /* Server didn't respond to interrupt_operation, \ so the signal thread destroyed the reply port. */ \ __err = EINTR; \ break; \ default: /* Quiet -Wswitch-enum. */ \ } \ __ss->intr_port = MACH_PORT_NULL; \ __err; \ }) \/* Mask of signals that cannot be caught, blocked, or ignored. */#define _SIG_CANT_MASK (__sigmask (SIGSTOP) | __sigmask (SIGKILL))/* Do an RPC to a process's message port. Each argument is an expression which returns an error code; each expression may be evaluated several times. FETCH_MSGPORT_EXPR should fetch the appropriate message port and store it in the local variable `msgport'. FETCH_REFPORT_EXPR should fetch the appropriate message port and store it in the local variable `refport' (if no reference port is needed in the call, then FETCH_REFPORT_EXPR should be simply KERN_SUCCESS or 0). Both of these are assumed to create user references, which this macro deallocates. RPC_EXPR should perform the desired RPC operation using `msgport' and `refport'. The reason for the complexity is that a process's message port and reference port may change between fetching those ports and completing an RPC using them (usually they change only when a process execs). The RPC will fail with MACH_SEND_INVALID_DEST if the msgport dies before we can send the RPC request; or with MIG_SERVER_DIED if the msgport was destroyed after we sent the RPC request but before it was serviced. In either of these cases, we retry the entire operation, discarding the old message and reference ports and fetch them anew. */#define HURD_MSGPORT_RPC(fetch_msgport_expr, fetch_refport_expr, rpc_expr) \({ \ error_t __err; \ mach_port_t msgport, refport = MACH_PORT_NULL; \ do \ { \ /* Get the message port. */ \ if (__err = (fetch_msgport_expr)) \ break; \ /* Get the reference port. */ \ if (__err = (fetch_refport_expr)) \ { \ /* Couldn't get it; deallocate MSGPORT and fail. */ \ __mach_port_deallocate (__mach_task_self (), msgport); \ break; \ } \ __err = (rpc_expr); \ __mach_port_deallocate (__mach_task_self (), msgport); \ if (refport != MACH_PORT_NULL) \ __mach_port_deallocate (__mach_task_self (), refport); \ } while (__err == MACH_SEND_INVALID_DEST || \ __err == MIG_SERVER_DIED); \ __err; \})/* Some other parts of the library need to preempt signals, to detect errors that should not result in a POSIX signal. For example, when some mapped region of memory is used, an extraneous SIGSEGV might be generated when the mapping server returns an error for a page fault. */struct hurd_signal_preempt { /* Function to examine a thread receiving a given signal. The handler is called even for blocked signals. This function is run in the signal thread, with THREAD's sigstate locked; it should be as simple and robust as possible. THREAD is the thread which is about to receive the signal. SIGNO and SIGCODE would be passed to the normal handler. If the return value is SIG_DFL, normal signal processing continues. If it is SIG_IGN, the signal is ignored. Any other value is used in place of the normal handler. */ sighandler_t (*handler) (thread_t thread, int signo, int sigcode); int first, last; /* Range of sigcodes this handler wants. */ struct hurd_signal_preempt *next; /* Next handler on the chain. */ };extern struct hurd_signal_preempt *_hurd_signal_preempt[NSIG];extern struct mutex _hurd_signal_preempt_lock;#endif /* hurd/signal.h */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -