Signal handling tune up.
Pierre A. Humblet
Wed Aug 20 17:48:00 GMT 2003
Christopher Faylor wrote:
>>If you do something like:
>> sigframe thisframe;
>> sig_dispatch_pending ();
>>then the signal dispatch will happen when foo returns, not when
>>sig_dispatch_pending returns. The goal is that, in most cases, the
>>function closest to the user should be the one that gets "interrupted".
>Well, that is what I thought the goal was, but looking at the sigframe
>code again it doesn't work that way. If it did work that way then the
>current call to call_signal_handler_now in sigreturn wouldn't be
>necessary, although the stack pressue would be even greater.
>So, I don't know why I put that explicit call in that function. It's
>probably superfluous, as you suspect.
After sleeping over this I have a new hypothesis, kind of just
the opposite of what we were thinking above.
interrupt_on_return will walk the stack and find an
"interruptible" address in the user code (outside of cygwin).
The handler starts when returning from that frame (closest
to the user).
sigframe::call_signal_handler () undoes that and forces an
immediate run of the handler. So it makes sense to use it
in sig_dispatch_pending ().
But now the plot thickens.
The sigframe has a "* sigthread" member, and the sigthread as an
"exception" member, which is initialized to 0 at sigframe creation time
but can be explicitly set by sigframe::set
The only place (AFAICS) where it is used is in sig_send, which has an
"exception" argument that defaults to 0 and that is only used when
running in the mainthread.
The only (AFAICS) place where the sig_send "exception" is set
is when handle_exceptions calls sig_send.
The only place where I find "sigthread::exception" used is in
interrupt_on_return, which won't check for interruptibility if
"exception" is true.
That's efficient because a) it guarantees success without walking the
stack and b) the handler is called faster.
I am wondering if the same mechanism couldn't/shouldn't be used
in sig_dispatch_pending () as well, calling
sig_send (myself, __SIGFLUSH, 1) when in the mainthread.
If that works it would be more efficient and we wouldn't need
a sigframe in sig_dispatch_pending (), nor a call to
sigframe::call_signal_handler (), after all.
While looking at the code, I got worried by interrupt_setup().
As soon as sigsave.sig = sig; is executed, the sigsave can be
picked up by a terminating handler.
Thus shouldn't sigsave.sig = sig; be the last statement in
interrupt_setup() to avoid a race condition?
More information about the Cygwin-patches