diff options
Diffstat (limited to 'winsup/cygwin/how-signals-work.txt')
-rw-r--r-- | winsup/cygwin/how-signals-work.txt | 113 |
1 files changed, 0 insertions, 113 deletions
diff --git a/winsup/cygwin/how-signals-work.txt b/winsup/cygwin/how-signals-work.txt deleted file mode 100644 index 26e5ee1ba..000000000 --- a/winsup/cygwin/how-signals-work.txt +++ /dev/null @@ -1,113 +0,0 @@ -Copyright 2001, 2002, 2003 Red Hat Inc., Christopher Faylor - -[this information is currently out-of-date] -How do signals work? - -On process startup, cygwin starts a secondary thread that deals with signals. -This thread contains a loop which blocks waiting for information to show up -on a pipe whose handle (sendsig) is currently stored in _pinfo (this may change). - -Communication on the sendsig pipe is via the 'sigelem' structure. This -structure is filled out by the sig_send function with information about the -signal being sent, such as (as of this writing) the signal number, the -originating pid, the originating thread, and the address of the mask to -use (this may change). - -If the signal is not blocked, then the function "sig_handle" is called -with the signal number as an argument. This is a fairly straightforward -function. It first checks to see if the signal is special in any way. - -A special signal is something like SIGKILL or SIGSTOP. The user has no -control over how those signals affect a UNIX process. If a SIGKILL is -received then sig_handle calls exit_sig to exit the process. If SIGSTOP -is called then sig_handle calls the regular signal dispatch function -with a special function argument "sig_handle_tty_stop". The signal -dispatch function is described below. - -An uncaught signal like SIGTERM or SIGHUP will cause the process to exit -with the standard UNIX exit values. Uncaught signals like SIGUSR1 are -ignored, as on UNIX. - -If the signal has an associated signal handler, then the setup_handler -function is eventually called. It is passed the signal, the address of -the handler, and a standard UNIX sigaction structure. The meat of -signal processing is in setup_handler. - -setup_handler has a "simple" task. It tries to stop the appropriate -thread and redirect its execution to the signal handler function. -Currently, the "appropriate thread" is only the main thread. Someday -we'll have to change this to allow cygwin to interrupt other user -threads. - -To accomplish its task, setup_handler first inspects the static sigsave -structure. This structure contains information on any not-yet-handled -signals that may have been set up by a previous call to setup_handler -but not yet dispatched in the main thread. If the sigsave structure -seems to be "active", then a "pending" flag is set (see below) and the -function returns. Otherwise processing continues. - -After determining that sigsave is available, setup_handler will take one -of two routes, depending on whether the main thread is executing in the -cygwin DLL or is currently in "user" code. We'll discuss the cygwin DLL -case first. - -If sigsave seems to be available, then the frame information for the -main thread is inspected. This information is set by any cygwin -function that is known to block (such as _read()), usually by calling -'sigframe thisframe (mainthread)' in the cygwin function. This call -sets up information about the current stack frame of an executing cygwin -process. Any function which uses 'sigframe thisframe' should be signal -aware. It should detect when a signal has arrived and return -immediately. This method is also used throughout the DLL to ensure -accurate frame info for the executing function. So, you'll see it -sprinkled liberally throughout the DLL, usually at places where -empirical tests have indicated problems finding this address via the -brute force method stack walking method employed in setup_handler. - -So, if mainframe is active, that means that we have good information -about the state of the main thread. Cygwin uses the stack frame info -from this structure to insert a call to the assembly language function -'sigdelayed' in place of the main thread's normal return address. So, -when a call to (e.g.) _read returns after detecting a signal, it does -not return to its caller. Rather, it returns to sigdelayed. - -The sigdelayed function saves a lot of state on the stack and sets the -signal mask as appropriate for POSIX. It uses information from the -sigsave structure which has been filled in by interrupt_on_return, as -called by setup_handler. sigdelayed pushes a "call" to the function -"sigreturn" on the stack. This will be the return address seen by the -signal handler. After setting up the return value, modifying the signal -mask, and saving other information on the stack, sigreturn clears the -sigsave structure (so that setup_handler can use it) and jumps to the -signal handler function. And, so a UNIX signal handler function is -emulated. - -The signal handler function operates as normal for UNIX but, upon -return, it does not go directly back to the return address of the -original cygwin function. Instead it returns to the previously -mentioned 'sigreturn' assembly language function. - -sigreturn resets the process mask to its state prior to calling the -signal handler. It checks to see if any new signals have come in and -calls the handler for them now, ensuring that the order of signal -arrival is more or less maintained. It checks to see if a cygwin -routine has set a special "restore this errno on returning from a -signal" value and sets errno to this, if so. Finally, it restores all -of the register values that were in effect when sigdelayed was called. - -Ok, you thought I had forgotten about the 'pending' stuff didn't you? -Well, if you can rewind up to the discussion of sig_handle, we'll return -to the situation where sigsave was currently active. In this case, -setup_handler will set a "pending" flag, will reincrement the appropriate -element of the above signal array, and will return 0 to indicate that -the interrupt did not occur. Otherwise setup_handler returns 1. - -For pending signals, the theory is that the signal handler thread will -be forced to be rerun by having some strategic cygwin function call -sig_send with a __SIGFLUSH "argument" to it. This causes the signal -handler to rescan the signal array looking for pending signals. - -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 -called by a high level process like kill(). You would use sig_send -to send a __SIGFLUSH to the signal thread. |