Signals: -------- A Signal is an asynchronous notification to an application , either solicited or unsolicited , by the kernel. The application can override default actions for signals, by specifying handlers to be invoked on signal occurences. Ofcourse, only certain signals can be overridden. Thread of execution: ------------------- A thread can be defined as a set of instrns, with start state defined as , where EIPstart ,ESPstart are valid members in an address space ( and ofcourse stackSize < AddressSpaceSize.) Whats special about a signal handler in user space ? ---------------------------------------------------- The semblance between signal handlers and ISRs is specious. The only similarity is that both are seperate threads of execution, causing the previous thread to stall, and both can be disabled and enabled. Signal handlers are special. Is it so ? NO but YES ! They are NOT special. BECAUSE -> A signal handler represents a thread of execution in user space just like the main program. They can open files, write files, issue system calls that sleep, and do anything bounded by user privileges. They are special. BECAUSE -> The only fuzzy thing about signal handlers is that WE ( main thread of execution ) dont directly call the signal handler. We ( The main thread of execution ) do not know where it returns. And it is because of this reason, signal handlers need to considered special. Otherwise they are normal piece of code. The second perspective is the key for multi-threading. KERNEL's responsibility in delivering signals --------------------------------------------- Before delving into this, lets c how the kernel delivers a signal to a process. From the perspective of the kernel, he can prefer to choose one of the following solutions to deliver a signal. 1. If the kernel supports multiple user threads in a single address space, then the kernel can create a seperate thread in the user space that starts with the SIGNAL HANDLER's start address. The kernel's thread scheduling sub-system would ensure that the thread is scheduled. In a nutshell, a kernel with multiThreading support. 2. The kernel could save the context of the current thread of execution in user-space ( if it stores in kernel space, there would b no diff between soln 1 and 2 ) itself and overwrite the process's thread context ( the one inside the kernel space ) with the signal handlers context. For a kernel, which doesnt support multiple user threads in a single addressspace, there would always be only 1 thread context for a process. Linux ----- Linux chooses solution 2. While delivering a signal, Linux stores the thread state of the previous thread of execution in the user-stack. Thus this information could be exploited to perform multiThreading. Infact the job of the threadScheduler in a kernel supporting multiple user threads, can be done by a signal handler in user-space, in a kernel which doesn't recognize multiple threads of execution in user space. The structure of user-stack when an ordinary signal is delivered looks like: ----------------------------- <----- ESP when a sig Handler is invoked. Return Address -------------------------- ----------------------------- | sigNumber | | ----------------------------- | struct sigcontext | ( includes the entire register context ) | ----------------------------- | fpstate | ----------------------------- | extra mask[] | ----------------------------- | popl %eax <--------------------------------- movl $__NR_sigreturn int $0x80 ----------------------------- /* * STACK high address. Grows upwards. * The entire context of previous thread is accessible to the * signal handler althoug this is not documented. One can * verify this information with the linux kernel sources. * See the data structure "struct sigframe". */ The "__NR_sigreturn" system call helps the kernel to restore the previous thread's context. As shown above, when the signal handler exits, it returns to an area in stack where the kernel had already set the trap to make the signal handler execute the system call transparently. Hereby the kernel assumes certain amount of innocence on the part of the signal handler. He assumes that he wont play with the context stored in the stack. Ok, by now, a skeptical reader or a hacker, would find a big security loop hole in this arrangement. There is a chance that the appln could grab kernel privilege by playing with the context stored in the stack. But Linux is not so dumb. While restoring signal context, he just deliberately ORs the segment register values with 0x03.( 0x03 -> Appln privilege in 386+ terms ) thereby precluding any chance for hackers. MultiThreading: Now we have everything in hand. Saving a context is as simple as a MEMCPY and the same applies to restoring a context.