tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: sigqueue code paths



First, the basic (since forever) unix signal handling method, then some
NetBSD code pointers (and I'm sure you will find the rest).

Signal generation (causing a signal to be sent to a process) you have
largely found I believe - either a sys call (from the process to
receive the signal, or another) or some async event (interrupt from the
clock, or some device driver) decides a signal needs to be delivered to
a process, and arranges to queue it (it used to be just set a bit in the
signal pending word, but I'm sure it is more complex these days).

That code also takes care of doing nothing should the signal not be wanted
by the receiving process.

Next note, that if we're doing this, kernel code is obviously running,
so before any user code can execute again, the kernel needs to execute the
"return to user space" function(s).    Part of that is selecting which
process runs next (if we have actually delivered a signal to a process it
will have been made runnable, as you noted, so that process is a candidate
for being the next - or one of the next on a multiprocessor - process to be
given the cpu).

One of the steps in returning to user space is to look and see if there are
any pending signals.   If there are, rather than returning to where the
process was previously executing, an "interrupt" stack context is created
for the process, and it is set to resume at its signal handler - that step
is obviously highly machine (and emulation) dependent.   Then when the
kernel returns to user space, the user process will run is signal handler.

In NetBSD, return to user space is (partly) lwp_userret() in kern/kern_lwp.c
In there you will see...

                if ((l->l_flag & (LW_PENDSIG | LW_WCORE | LW_WEXIT)) ==
                    LW_PENDSIG) {
                        mutex_enter(p->p_lock);
                        while ((sig = issignal(l)) != 0)
                                postsig(sig);
                        mutex_exit(p->p_lock);
                }

That is checking if there is a pending signal, and if so, deliver it
to the process - you can follow postsig() to see how it gets down into
the arch/emul specific sig setup routine to actually set the environ for
the user process, and issignal() to see how the pending signals are
examined and one is selected to deliver first (but think carefully
about just what the while loop quoted above actually means...)
Both of those are in kern/kern_sig.c

kre



Home | Main Index | Thread Index | Old Index