From: rcswebb on 19 Jun 2010 19:02 Hello, I'm writing some threaded shared library code that will be used by programs that execute a main event loop and exit via a signal handler i.e. static void handle_signal(int) { exit_flag = true; } int main() { while(!exit_flag) { //stuff } return 0; } I wish to preserve this behaviour by, in theory at least, blocking SIGTERM and SIGINT in each of the threads my library code creates thus allowing only the main thread to receive the signal. So far I've tried: sigset_t set; sigfillset(&set); pthread_sigmask(SIG_SETMASK, &set, 0); in the function my thread executes, the theory being, I mask every signal in my threads the library creates. The problem is, my signal handler in the main thread doesn't seem to be firing. I'd appreciate any advice or insights on how to solve this? The only restriction I have is that the code that uses my library (i.e. the main thread) has to remain agnostic to the presence of threads in the library and the associated signal handling issues. Regards, Richard.
From: Ersek, Laszlo on 20 Jun 2010 05:12 On Sat, 19 Jun 2010, rcswebb wrote: > I'm writing some threaded shared library code that will be used by > programs that execute a main event loop and exit via a signal handler > i.e. > > static void handle_signal(int) > { > exit_flag = true; > } > > int main() > { > while(!exit_flag) > { > //stuff > } > return 0; > } > > I wish to preserve this behaviour by, in theory at least, blocking > SIGTERM and SIGINT in each of the threads my library code creates thus > allowing only the main thread to receive the signal. This approach is sort of mandatory. Even with "exit_flag" being of type "volatile sig_atomic_t", you can only rely on thread T noticing a change in "exit_flag" if the thread interrupted by the signal and executing the handler modifying "exit_flag" is the same thread T. That is, if the main thread is the one checking "exit_flag", then the main thread must be the one modifying it in the handler, too. I'm too lazy to look up references, google >>Boehm volatile sigatomic_t<< [sic]. > So far I've tried: > > sigset_t set; > sigfillset(&set); > pthread_sigmask(SIG_SETMASK, &set, 0); > > in the function my thread executes, the theory being, I mask every > signal in my threads the library creates. There's a race condition in that. An async signal could be delivered to your thread before it executes pthread_sigmask(). I'd recommend blocking SIGTERM and SIGINT in the main thread before starting any other threads. The subsequently created threads would inherit the signal mask. Finally, you could unblock those signals in the main thread if necessary. If the sub-threads, created directly by the main thread, create their own descendant threads, the latter again will inherit a signal mask that has those two signals blocked. For blocking SIGINT and SIGTERM in the main thread, I'd recommend emptying a signal set and adding only these two. Blocking all possible signals seems too heavy-handed. For example, you don't need to block asynchronous signals that the original (single threaded) program doesn't care about at all. Looking at the list of default signal actions in SUSv4 (<signal.h>): ----v---- The default actions are as follows: T Abnormal termination of the process. A Abnormal termination of the process [XSI] [Option Start] with additional actions. [Option End] I Ignore the signal. S Stop the process. C Continue the process, if it is stopped; otherwise, ignore the signal. ----^---- The default action is either to ignore the signal, or the delivery of the signal affects the entire process. It doesn't matter which thread is the victim. Synchronous signals are delivered to the offending thread anyway. > The problem is, my signal handler in the main thread doesn't seem to be > firing. After blocking the signals, have you set up the handler with sigaction() and unblocked the signals? > I'd appreciate any advice or insights on how to solve this? > > The only restriction I have is that the code that uses my library (i.e. > the main thread) has to remain agnostic to the presence of threads in > the library and the associated signal handling issues. That is impossible. For example, the main thread can't call sigprocmask() anymore; at least after your library created sub-threads. There are issues with fork(); see earlier threads in this group. If you don't recompile (or rather, relink) the original client application, just switch the pre-existent shared lib below it from single-threaded to multi-threaded, there might be issues with errno. In my opinion, it is risky if a "main thread" is oblivious to the presence of other threads in the same process. Why do you want to do this? Couldn't you achieve whatever you're trying to with child processes? lacos
|
Pages: 1 Prev: Simple hack to get $600 to your home. Next: reader writer semaphores |