minor cleanup

This commit is contained in:
Christopher Faylor 2004-03-14 05:35:19 +00:00
parent ad22734a88
commit 8308950ca5
1 changed files with 40 additions and 35 deletions

View File

@ -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 **