Signal Recognition

   

There are three places a thread checks to see if it has been signaled: at the end of every system call, when it wakes up from a sleep, and after handling a trap of some kind. The routine that checks for signals is issig(). The kernel routines real_sleep(), syscall(), and trap() each call issig() to see if any signals are pending for the thread.

The job of issig() is to determine what signal, if any, should be processed. issig() loops through the bits in p_sig and kt_sig looking for pending signals. If it finds no signals pending, it returns zero. If it finds a signal that is pending, it returns the number of the signal. The signal number is also placed in the thread structure, in kt_cursig.

Although this sounds like a relatively simple process, issig() does a few other things that add to its complexity. Most of the default actions for signals are handled by issig(). If the action for the signal is set to SIG_DFL, issig() looks at the signal number. Default actions are handled by issig() for SIGTSTP, SIGTTIN, SIGTTOUT, SIGSTOP, SIGCONT, SIGIO, SIGCANCEL, SIGPWR, SIGWINCH, SIGCLD, SIGURG, and SIGDIL.

Signals with an action of SIG_HOLD or SIG_IGN are handled by issig() too. If the action is SIG_IGN, the bit is reset and any siginfo that goes with it is thrown away. For SIG_HOLD, no action is taken the bit stays set, the siginfo stays, but the signal is not acted on.

Once issig() has found a signal that needs to be handled, it has one more step to do before returning. If the signal was directed at the process, then any siginfo data that goes with it is also attached to the process. issig() is working at the thread level, so when it returns a signal number, it is indicating that the current thread is to receive the signal. Just before it returns, issig()moves the siginfo data from the process to the thread so that the routines that actually handle the signal will be able to find it.

The second step in signal recognition is handled by the routine psig(). psig() looks at the value it kt_cursig to find the current signal number, then uses that to look up the signal action in the p_signal array in the proc structure. If the action is SIG_DFL, psig() takes the default action for those signals whose default actions weren't handled by issig(). These include SIGILL, SIGIOT, SIGBUS, SIGQUIT, SIGTRAP, SIGEMT, SIGFPE, SIGSEGV, SIGSYS, SIGXCPU, SIGXFSZ, and SIGGFAULT. In all these cases, a core file is generated for the process and the process is terminated.

Ignored and held signals don't make it to psig(), and those with default actions have now been handled either by issig() or psig(). What we're left with is a signal that has a user handler installed. psig() then calls the function sendsig() to prepare for calling that function.

psig() is also the route into the signal handler for synchronous signals such as SIGSEGV or SIGILL. These signals are caused by a thread trying to do an invalid operation. The invalid operation gets caught by the trap handler, which then calls psig() directly. In this way, these signals get handled immediately, not queued up to be found later. This detection happens in the trap() function in the kernel but this isn't the same as the detection of asynchronous signals in trap() that we mentioned above. In other words, trap() can generate a signal in two ways: first, for a trap of any kind, trap() checks to see if an asynchronous signal has been queued and needs to be handled; second, trap() checks to see if the exception that caused it to be called should immediately generate a synchronous signal.



HP-UX 11i Internals
HP-UX 11i Internals
ISBN: 0130328618
EAN: 2147483647
Year: 2006
Pages: 167

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net