Signal handling in multi-threaded applications.

Signal handling in multi-threaded applications.

Post by Krivenok D » Wed, 11 Jul 2007 04:35:49


Hello!

I know two kind of signals:
1) Asynchronous signals like SIGTERM or SIGINT.
These signals are typically generated using the kill() call.
2) Synchronous signals like SIGSEGV or SIGFPE.
These signals are generated by hardware and delivered to the
thread that caused the HW condition.

I also know about two different approaches to signal handling:
1) Synchronous handling of asynchronous signals using sigwait
system call.
In such a case a dedicated thread is used for calling
sigwait() in a loop.
2) Asynchronous handling of synchronous signals using signal
actions. This is a classic approach to signal handling.
Actions are set using sigaction() function.
However there is a limited set of functions that may be safety
called from within catching functions.
These functions are called "async-signal-safe".

One of "async-signal-safe" functions is sem_post() function.
It allows one to write code like this:

...
sig_atomic_t catched = 0;
sem_t semaphore;
...
sem_init(&semaphore,0,0);
...
int signals_handler(int signo)
{
catched = signo;
sem_post(&semaphore);
return 0;
}
...
...
int main()
{
...
// Init all.
...
// Start worker threads.
...
// Signal handling
while(1)
{
sig_wait(&semaphore);
// What signal has been received?
int signo = catched;
// Restore state.
catched = 0;
switch(signo)
{
case SIGTERM :
logg("SIGTERM received. Exiting.");
exit(-1);
case SIGSEGV :
logg("SIGSEGV received. It's really bad. Exiting.");
exit(-1);
default :
/* Handle other signals */
};
}
return 0;
}

Catching function is called asynchronously, but it consist of only
"async-signal-safe" functions.
In fact, real signal handling (switch operator) is synchronous.

The question arises, is this approach correct?
If so, why should I use sigwait? Why not to handle all signals
asynchronously (regardless of signal type)?

It seems to me that this approach isn't correct and has obvious or
hidden errors.
I'm newbie in UNIX programming and need some help :)

Thank you beforehand!
 
 
 

Signal handling in multi-threaded applications.

Post by Bin Che » Wed, 11 Jul 2007 08:57:47


it's not sigwait()?

Using sigwait() call in a thread that dedicated to signal handling,
this is because general assumption on which thread will receive the
signal when another thread kill() a signal to the thread
group(process) of POSIX.

At least on many POSIX thread implementation, when another process
kill() a signal to a thread groups, it is random to choose a thread to
be paused to handle the signal, so to make this event determined, a
programming scheme will be block all the async signal in most thread,
but only let one thread unblock it, so the signal will delivered to
this thread.

 
 
 

Signal handling in multi-threaded applications.

Post by Frank Cusa » Wed, 11 Jul 2007 10:20:55

n Mon, 09 Jul 2007 12:35:49 -0700 Krivenok Dmitry < XXXX@XXXXX.COM > wrote:

Don't forget the dreaded SIGPIPE, not generated by hardware.


This should (needs to) be volatile sig_atomic_t.


main() takes 2 arguments


sem_wait()


exit(1)


exit(1)


Looks great to me.


sigwait would allow the thread that generated a synchronous signal
to handle the signal itself, as opposed to some different signal-
handling thread having to do it. Off the top of my head, I can't
think of a use for that but I'm sure there is one. umm how about,
for a library, you don't want to mess with the app's signal handlers
and so you would want to process SIGPIPE yourself.

You might also want different threads to handle different signals.
Not sure why you would want that, but if you did you'd have to use
sigwait.


Looks pretty good for a noob. I'm impressed.
-frank
 
 
 

Signal handling in multi-threaded applications.

Post by scot » Wed, 11 Jul 2007 12:36:23

Frank Cusack < XXXX@XXXXX.COM > writes:


[snip


Well standards-wise 3 (and in reality four):

int
main(int argc, char **argv, char **envp, char **auxv);

envp is environment vector, auxv is typical on svr4-derived systems and
is used by the runtime linker and not generally used by a portable
application, but it's there if you want it.



How can a thread _waiting_ on a sigwait(2) system call raise a
synchronous signal?

scott
 
 
 

Signal handling in multi-threaded applications.

Post by Frank Cusa » Wed, 11 Jul 2007 13:05:38


sigset_t set;
int sig;
sigemptyset(&set);
sigaddset(&set, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &set, NULL);
write(...);
sigpending(&set);
if (sigismember(&set, SIGPIPE))
sigwait(&set, &sig);

So, the answer is, of course, it can't. However that doesn't stop
sigwait() from being used for SIGPIPE, perhaps others. Obviously
this doesn't work for SIGBUS, SIGSEGV. Well maybe it would, but
not correctly. Probably works for SIGFPE.

-frank
 
 
 

Signal handling in multi-threaded applications.

Post by Geoff Clar » Wed, 11 Jul 2007 21:32:05


No. Any arguments beyond the first two are non-standard. See the
description of the exec*() functions in POSIX:

"When a C-language program is executed as a result of this call,
it shall be entered as a C-language function call as follows:

int main (int argc, char *argv[]);

where argc is the argument count and argv is an array of character
pointers to the arguments themselves."

--
Geoff Clare < XXXX@XXXXX.COM >