minor cleanup
This commit is contained in:
parent
ad22734a88
commit
8308950ca5
|
@ -27,28 +27,29 @@ the perl script "gendef". This function notices exported cygwin
|
||||||
functions which are labelled as SIGFE and generates a front end assembly
|
functions which are labelled as SIGFE and generates a front end assembly
|
||||||
file "sigfe.s" which contains the wrapper glue necessary for every
|
file "sigfe.s" which contains the wrapper glue necessary for every
|
||||||
function to call sigfe prior to actually dispatching to the real cygwin
|
function to call sigfe prior to actually dispatching to the real cygwin
|
||||||
function. This generated function contains low-level signal related
|
function. This generated file contains low-level signal related
|
||||||
functions: _sigfe, _sigbe, sigdelayed, sigreturn, longjmp, and setjmp.
|
functions: _sigfe, _sigbe, sigdelayed, sigreturn, longjmp, and setjmp.
|
||||||
|
|
||||||
The signal stack maintained by sigfe/sigbe and friends is a secondary
|
The signal stack maintained by sigfe/sigbe and friends is a secondary
|
||||||
shadow stack. Addresses from this stack are swapped into the "real"
|
shadow stack. Addresses from this stack are swapped into the "real"
|
||||||
stack as needed to control program flow. The intent is that executing
|
stack as needed to control program flow. The intent is that executing
|
||||||
cygwin functions will still see roughly the same stack layout and will
|
cygwin functions will still see the same stack layout as if they had
|
||||||
be able to retrieve arguments from the stack but will always return
|
been called directly and will be able to retrieve arguments from the
|
||||||
to the _sigbe routine so that any signal handlers will be properly
|
stack but will always return to the _sigbe routine so that any signal
|
||||||
called.
|
handlers will be properly called.
|
||||||
|
|
||||||
Upon receipt of a "non-special" (see below) signal, the function
|
Upon receipt of a "non-special" (see below) signal, the function
|
||||||
sigpacket::process is called. This function determines what action, if
|
sigpacket::process is called. This function determines what action, if
|
||||||
any, to take on the signal. Possible actions are: Ignore the signal (e.g.,
|
any, to take on the signal. Possible actions are: Ignore the signal
|
||||||
SIGUSR1), terminate the program (SIGKILL, SIGTERM), stop the program
|
(e.g., SIGUSR1), terminate the program (SIGKILL, SIGTERM), stop the
|
||||||
(SIGSTOP, SIGTSTP, etc.), wake up a sigwait or sigwaitinfo in a
|
program (SIGSTOP, SIGTSTP, etc.), wake up a sigwait or sigwaitinfo in a
|
||||||
targetted thread, or call a signal handler (possibly in a thread).
|
targetted thread, or call a signal handler (possibly in a thread). If
|
||||||
If no thread information has been sent to sigpacket::process, it determines
|
no thread information has been sent to sigpacket::process, it determines
|
||||||
the correct thread to use based on various heuristics, as per UNIX.
|
the correct thread to use based on various heuristics, as per UNIX. As
|
||||||
Signals sent via the UNIX kill() function are normally sent to the
|
per linux, the only time a handler is called in a thread is when there
|
||||||
main thread. Ditto signals sent as the result of pressing tty keys,
|
is some kind of fault like SIGSEGV, SIGILL, etc. Signals sent via the
|
||||||
like CTRL-C.
|
UNIX kill() function are normally sent to the main thread. Ditto
|
||||||
|
signals sent as the result of pressing tty keys, like CTRL-C.
|
||||||
|
|
||||||
Signals which stop a process are handled by a special internal handler:
|
Signals which stop a process are handled by a special internal handler:
|
||||||
sig_handle_tty_stop. Some signals (e.g., SIGKILL, SIGSTOP) are
|
sig_handle_tty_stop. Some signals (e.g., SIGKILL, SIGSTOP) are
|
||||||
|
@ -73,26 +74,26 @@ parent via a false value. Otherwise processing continues.
|
||||||
|
|
||||||
(For pending signals, the theory is that the signal handler thread will
|
(For pending signals, the theory is that the signal handler thread will
|
||||||
be forced to be rerun by having some strategic cygwin function call
|
be forced to be rerun by having some strategic cygwin function call
|
||||||
sig_send with a __SIGFLUSH "argument" to it. This causes the signal
|
sig_send with a __SIGFLUSH argument. This causes the signal handler to
|
||||||
handler to rescan the signal array looking for pending signals.)
|
rescan the signal array looking for pending signals.)
|
||||||
|
|
||||||
After determining that it's ok to send a signal, setup_handler will lock
|
After determining that it's ok to send a signal, setup_handler will lock
|
||||||
the cygtls stack to ensure that it has complete access. It will then
|
the cygtls stack to ensure that it has complete access. It will then
|
||||||
inspect the thread's 'incyg' element. If this is true, the thread is
|
inspect the thread's 'incyg' boolean. If this is true, the thread is
|
||||||
currently executing a cygwin function. If it is false, the thread is
|
currently executing a cygwin function. If it is false, the thread is
|
||||||
unlocked and it is assumed that the thread is executing "user" code.
|
unlocked and it is assumed that the thread is executing "user" code.
|
||||||
The actions taken by setup_handler differ based on whether the program
|
The actions taken by setup_handler differ based on whether the program
|
||||||
is executing a cygwin routine or not.
|
is executing a cygwin routine or not.
|
||||||
|
|
||||||
If the program is executing a cygwin routine, then the
|
If the program is executing a cygwin routine, then the
|
||||||
interrupt_on_return function is called which sets the address of the
|
interrupt_on_return function is called which causes the address of the
|
||||||
'sigdelayed' function is pushed onto the thread's signal stack, and the
|
'sigdelayed' function to be pushed onto the thread's signal stack, and
|
||||||
signal's mask and handler is saved in the tls structure. Then the
|
the signal's mask and handler to be saved in the tls structure. After
|
||||||
'signal_arrived' event is signalled, as well as any thread-specific wait
|
performing these operations, the 'signal_arrived' event is signalled, as
|
||||||
event.
|
well as any thread-specific wait event.
|
||||||
|
|
||||||
Since the sigdelayed function was saved on the thread's signal stack,
|
Since the sigdelayed function was saved on the thread's signal stack,
|
||||||
when the cygwin functio returns, it will eventually return to the
|
when the cygwin function returns, it will eventually return to the
|
||||||
sigdelayed "front end". The sigdelayed function will save a lot of
|
sigdelayed "front end". The sigdelayed function will save a lot of
|
||||||
state on the stack and set the signal mask as appropriate for POSIX.
|
state on the stack and set the signal mask as appropriate for POSIX.
|
||||||
It uses information from the _cygtls structure which has been filled in
|
It uses information from the _cygtls structure which has been filled in
|
||||||
|
@ -124,13 +125,14 @@ SA_RESTART.
|
||||||
|
|
||||||
UNIX allows some blocking functions to be interrupted by a signal
|
UNIX allows some blocking functions to be interrupted by a signal
|
||||||
handler and then return to blocking. In cygwin, so far, only
|
handler and then return to blocking. In cygwin, so far, only
|
||||||
read/readv() operate in this fashion. To accommodate this behavior,
|
read/readv() and the wait* functions operate in this fashion. To
|
||||||
readv notices when a signal comes in and then calls the _cygtls function
|
accommodate this behavior, a function notices when a signal comes in and
|
||||||
'call_signal_handler_now'. 'call_signal_handler_now' emulates the
|
then calls the _cygtls function 'call_signal_handler_now'.
|
||||||
behavior of both sigdelayed and sigreturn. It sets the appropriate
|
'call_signal_handler_now' emulates the behavior of both sigdelayed and
|
||||||
masks and calls the handler, returning true to the caller if SA_RESTART
|
sigreturn. It sets the appropriate masks and calls the handler,
|
||||||
is active. If SA_RESTART is active, readv will loop. Otherwise
|
returning true to the caller if SA_RESTART is active. If SA_RESTART is
|
||||||
it will return -1 and set the errno to EINTR.
|
active, the function will loop. Otherwise it will typically return -1
|
||||||
|
and set the errno to EINTR.
|
||||||
|
|
||||||
Phew. So, now we turn to the case where cygwin needs to interrupt the
|
Phew. So, now we turn to the case where cygwin needs to interrupt the
|
||||||
program when it is not executing a cygwin function. In this scenario,
|
program when it is not executing a cygwin function. In this scenario,
|
||||||
|
@ -142,12 +144,15 @@ suspend a process executing a win32 call can cause disastrous results,
|
||||||
especially on Win9x.
|
especially on Win9x.
|
||||||
|
|
||||||
If the process is executing in an unsafe location then setup_handler
|
If the process is executing in an unsafe location then setup_handler
|
||||||
will return false as in the case above. Otherwise, the current location
|
will (quickly!) return false as in the case above. Otherwise, the
|
||||||
of the thread is pushed on the thread's signal stack and the thread is
|
current location of the thread is pushed on the thread's signal stack
|
||||||
redirected to the sigdelayed function via the win32 "SetThreadContext"
|
and the thread is redirected to the sigdelayed function via the win32
|
||||||
call. Then the thread is restarted using the win32 "ResumeThread" call
|
"SetThreadContext" call. Then the thread is restarted using the win32
|
||||||
and things proceed as per the sigdelayed discussion above.
|
"ResumeThread" call and things proceed as per the sigdelayed discussion
|
||||||
|
above.
|
||||||
|
|
||||||
This leads us to the sig_send function. This is the "client side" part
|
This leads us to the sig_send function. This is the "client side" part
|
||||||
of the signal manipulation process. sig_send is the low-level function
|
of the signal manipulation process. sig_send is the low-level function
|
||||||
called by a high level process like kill() or pthread_kill().
|
called by a high level process like kill() or pthread_kill().
|
||||||
|
|
||||||
|
** More to come **
|
||||||
|
|
Loading…
Reference in New Issue