sigaction.c revision 9acbbeaf2a1ffe5c14b244867d427714fab43c5c
3853N/A * The contents of this file are subject to the terms of the 3853N/A * Common Development and Distribution License (the "License"). 3853N/A * You may not use this file except in compliance with the License. 3853N/A * See the License for the specific language governing permissions 3853N/A * and limitations under the License. 3853N/A * When distributing Covered Code, include this CDDL HEADER in each 3853N/A * If applicable, add the following below this CDDL HEADER, with the 3853N/A * fields enclosed by brackets "[]" replaced with your own identifying 3853N/A * information: Portions Copyright [yyyy] [name of copyright owner] 3853N/A * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3853N/A * Use is subject to license terms. 3853N/A#
pragma ident "%Z%%M% %I% %E% SMI" 3853N/A * Return true if the valid signal bits in both sets are the same. 3853N/A * We only test valid signal bits, not rubbish following MAXSIG 3853N/A * if (s1 & fillset) == (s2 & fillset) then (s1 ^ s2) & fillset == 0 3853N/A * Common code for calling the user-specified signal handler. 3853N/A * If we are taking a signal while parked or about to be parked 3853N/A * on __lwp_park() then remove ourself from the sleep queue so 3853N/A * that we can grab locks. The code in mutex_lock_queue() and 3853N/A * cond_wait_common() will detect this and deal with it when 3853N/A * Get a self-consistent set of flags, handler, and mask 3853N/A * while holding the sig's sig_lock for the least possible time. 3853N/A * We must acquire the sig's sig_lock because some thread running 3853N/A * in sigaction() might be establishing a new signal handler. 3853N/A * No locking for a child of vfork(). 3853N/A * If the signal is SIGPROF with an si_code of PROF_SIG, 3853N/A * then we assume that this signal was generated by 3853N/A * setitimer(ITIMER_REALPROF) set up by the dbx collector. 3853N/A * If the signal is SIGEMT with an si_code of EMT_CPCOVF, 3853N/A * then we assume that the signal was generated by 3853N/A * a hardware performance counter overflow. 3853N/A * In these cases, assume that we need no locking. It is the 3853N/A * monitoring program's responsibility to ensure correctness. 3853N/A /* we wish this assignment could be atomic */ 3853N/A * Set the proper signal mask and call the user's signal handler. 3853N/A * (We overrode the user-requested signal mask with maskset 3853N/A * so we currently have all blockable signals blocked.) 3853N/A * We would like to ASSERT() that the signal is not a member of the 3853N/A * signal mask at the previous level (ucp->uc_sigmask) or the specified 3853N/A * signal mask for sigsuspend() or pollsys() (self->ul_tmpmask) but 3853N/A * /proc can override this via PCSSIG, so we don't bother. 3853N/A * We would also like to ASSERT() that the signal mask at the previous 3853N/A * level equals self->ul_sigmask (maskset for sigsuspend() / pollsys()), 3853N/A * but /proc can change the thread's signal mask via PCSHOLD, so we 3853N/A * don't bother with that either. 3853N/A /* the sigsuspend() or pollsys() signal mask */ 3853N/A /* the signal mask at the previous level */ 3853N/A * If this thread has been sent SIGCANCEL from the kernel 3853N/A * or from pthread_cancel(), it is being asked to exit. 3853N/A * The kernel may send SIGCANCEL without a siginfo struct. 3853N/A * If the SIGCANCEL is process-directed (from kill() or 3853N/A * sigqueue()), treat it as an ordinary signal. 3853N/A /* SIGCANCEL is ignored by default */ 3853N/A * If this thread has been sent SIGAIOCANCEL (SIGLWP) and 3853N/A * we are an aio worker thread, cancel the aio request. 3853N/A /* SIGLWP is ignored by default */ 4107N/A * If this is a floating point exception and the queue 4107N/A * is non-empty, pop the top entry from the queue. This 4107N/A * is to maintain expected behavior. 3853N/A * take_deferred_signal() is called when ul_critical and ul_sigdefer become 3853N/A * zero and a deferred signal has been recorded on the current thread. 3853N/A * We are out of the critical region and are ready to take a signal. 3853N/A * The kernel has all signals blocked on this lwp, but our value of 3853N/A * ul_sigmask is the correct signal mask for the previous context. 3853N/A * We call _private_getcontext (a libc-private synonym for 3853N/A * _getcontext) rather than _getcontext because we need to 3853N/A * avoid the dynamic linker and link auditing problems here. 3853N/A * If the application signal handler calls setcontext() on 3853N/A * the ucontext we give it, it returns here, then we return. 3853N/A * Do this in case we took a signal while in a cancelable system call. 3853N/A * It does no harm if we were not in such a system call. 3853N/A * If we are not in a critical region and are 3853N/A * not deferring signals, take the signal now. 3853N/A return;
/* call_user_handler() cannot return */ 3853N/A * We are in a critical region or we are deferring signals. When 3853N/A * we emerge from the region we will call take_deferred_signal(). 3853N/A * Make sure that if we return to a call to __lwp_park() 3853N/A * or ___lwp_cond_wait() that it returns right away 3853N/A * (giving us a spurious wakeup but not a deadlock). 4107N/A * Return to the previous context with all signals blocked. 4107N/A * We will restore the signal mask in take_deferred_signal(). 4107N/A * Note that we are calling the system call trap here, not 4107N/A * the _setcontext() wrapper. We don't want to change the 4107N/A * thread's ul_sigmask by this operation. tact = *
nact;
/* make a copy so we can modify it */ * To be compatible with the behavior of SunOS 4.x: * If the new signal handler is SIG_IGN or SIG_DFL, do * not change the signal's entry in the siguaction array. * This allows a child of vfork(2) to set signal handlers * to SIG_IGN or SIG_DFL without affecting the parent. * This also covers a race condition with some thread * setting the signal action to SIG_DFL or SIG_IGN * when the thread has also received and deferred * that signal. When the thread takes the deferred * signal, even though it has set the action to SIG_DFL * or SIG_IGN, it will execute the old signal handler * anyway. This is an inherent signaling race condition * A child of vfork() is not allowed to change signal * handlers to anything other than SIG_DFL or SIG_IGN. * Always catch these signals. * We need SIGCANCEL for pthread_cancel() to work. * We need SIGAIOCANCEL for aio_cancel() to work. * We detect setting the disposition of SIGIO just to set the * _sigio_enabled flag for the asynchronous i/o (aio) code. * Calling set_parking_flag(curthread, 1) informs the kernel that we are * calling __lwp_park or ___lwp_cond_wait(). If we take a signal in * the unprotected (from signals) interval before reaching the kernel, * sigacthandler() will call set_parking_flag(curthread, 0) to inform * the kernel to return immediately from these system calls, giving us * a spurious wakeup but not a deadlock. else if (
park == 0)
/* schedctl failed, do it the long way */ * Tell the kernel to block all signals. * Use the schedctl interface, or failing that, use __lwp_sigmask(). * This action can be rescinded only by making a system call that * __lwp_sigmask(), __sigprocmask(), __setcontext(), * __sigsuspend() or __pollsys(). * In particular, this action cannot be reversed by assigning * scp->sc_sigblock = 0. That would be a way to lose signals. * See the definition of restore_signals(self). * _private_setcontext has code that forcibly restores the curthread * pointer in a context passed to the setcontext(2) syscall. * Certain processes may need to disable this feature, so these routines * provide the mechanism to do so. * (As an example, branded 32-bit x86 processes may use %gs for their own * purposes, so they need to be able to specify a %gs value to be restored * on return from a signal handler via the passed ucontext_t.) * Returning from the main context (uc_link == NULL) causes * the thread to exit. See setcontext(2) and makecontext(3C). * Restore previous signal mask and context link. * We have a deferred signal present. * The signal mask will be set when the * signal is taken in take_deferred_signal(). * We don't know where this context structure has been. * Preserve the curthread pointer, at least. * Allow this feature to be disabled if a particular process #
error "none of __sparc, __amd64, __i386 defined" * Make sure that if we return to a call to __lwp_park() * or ___lwp_cond_wait() that it returns right away * (giving us a spurious wakeup but not a deadlock). * It is OK for setcontext() to return if the user has not specified thr_panic(
"setcontext(): __setcontext() returned");
* The assignments to self->ul_sigmask must be protected from * signals. The nuances of this code are subtle. Be careful. * Guard against children of vfork(). * Called at library initialization to set up signal handling. * All we really do is initialize the sig_lock mutexes. * All signal handlers are either SIG_DFL or SIG_IGN on exec(). * However, if any signal handlers were established on alternate * link maps before the primary link map has been initialized, * then inform the kernel of the new sigacthandler. * Common code for cancelling self in _sigcancel() and pthread_cancel(). * If the thread is at a cancellation point (ul_cancelable) then just * return and let _canceloff() do the exit, else exit immediately if * async mode is in effect. * Set up the SIGCANCEL handler for threads cancellation, * needed only when we have more than one thread, * or the SIGAIOCANCEL handler for aio cancellation, * called when aio is initialized, in __uaio_init().