Skip to content
Xiangyan Sun edited this page Sep 13, 2015 · 1 revision

Signal handling is perhaps the most complex and twisted part in flinux. The reason is Windows does not have a direct counterpart mechanism of Unix signals. Despite the compatibility bits, the signal handling process of flinux is actually quite similar to the approach that Linux kernel uses.

Signal handler thread

The main logic of processing signals can be found in syscall/sig.c, where there is also some special handling in dbt and almost everywhere.

Since Windows does not support signal handling directly, all signals are actually specifically emitted in flinux code and processed only by flinux processes. In Windows there is no async callbacks like Unix signals, in flinux we emulate this by creating an additional signal handling thread for listening coming signal requests.

When the signal subsystem is being initialized, it creates a named pipe object for the process, and then start the signal handler thread to listen on that thread. The named pipe operated at message mode and all data come in the named pipe is of struct signal_packet, that it is basically a RPC like mechanism. When one process wants to emit signals or do other communications with another process, it could create an client to the named pipe and send a procedure call.

Signal handling overview

In flinux, the signal handling process is roughly the following.

  • First, when a signal occurred, the flinux kernel searches a suitable thread (which is not blocking the incoming signal) to deliver the signal.
  • Once a thread is chosen, the kernel determines the current state of the thread, if the thread is executing in user code, it is immediately interrupted, and then the signal context setup routine is called to deliver the signal. Otherwise, when it is in kernel code, it replaces the return pointer to the kernel syscall handler to the signal context setup routine. When the kernel returns from the syscall, the signal context setup routine will be invoked and deliver the signal.
  • The signal context setup routine sets up various flags and contexts, then hand over the execution to user defined signal handler function.
  • When the signal handler function is finished, it will invoke the sigreturn system call (this is typically implemented in libc). In this case, the flinux sigreturn handler is invoked. It then restores the former execution context and resume execution of user code.

Blocking functions

In Linux, a blocking system call can be interrupted by signals. In most cases, the signal will return EINTR as the error code. In order to support this, flinux users signal_wait() to replace the stock WaitForMultipleObjects() or WaitForSingleObject() functions. The functions adds a signal event object to the wait list, and returns EINTR on signal deliver. The caller can then notice that the wait is interrupted and do properly actions.