safe signal handling

safe signal handling

Post by Eric Lukathe » Sun, 15 Jun 2003 03:50:45



Hello,

After reading W. R. Stevens' APUE, UNPv1, this group's FAQ and
related posts, and various web pages... my head is spinning. :o(
I'm still not sure what would be considered portable and safe signal
handling in my app described below:

- My app does not directly call any pthread functions. However, it
is linked with the pthread library since a 3rd party vendor's library
I link with is threaded. Actually, in my Makefile, I do use "-mt" and
"-lpthread". Does this matter (don't know but wanted to mention it in
case it does)?

- I've installed the same signal handler function for SIGTERM, SIGQUIT,
SIGINT, and SIGABRT. I want to catch these in order to call fclose(),
free(), and exit(). I've included each of these in a single function
that I'd like to call after receiving one of the signals mentioned
above.

- I have a critical section of code that I'd like to make sure isn't
interrupted or is performed atomically. It's basically a file copy
(fread(), fwrite()) section that I'd like to either succeed or fail as
one unit... not be interrupted in the middle of the file copy.

- I call sleep() for a user-defined amount of time (currently 30
seconds) after the app's main loop (for(;;)) completes before looping
again.

Here's what I have currently:

1) I'm using WRS' "Signal()" and "signal()" functions, which use
sigaction(), verbatim from his UNPv1 text. Should I still use this in
2003? Or is it considered outdated and/or unnecessary? Should I instead
just call sigaction()?

2) Should I use the example from APUE's signals chapter where he talks
about using sigsuspend() to protect my critical file copy code section
from interruption?

3) Do most UNIX releases nowadays support queued signals? How does this
contrast with asynchronous signals? Are these terms synonymous?

4) For reliability and safety reasons, do I need to implement some form
of signal checking that calls select() and then checks a pipe after an
arrived signal? This was discussed in another post to this group. I
don't know if doing this is applicable in all situations or not.

Any help, suggestions or guidance would be most appreciated. I'm having
trouble applying all the information I've read recently.

Many thanks,  -Eric

 
 
 

safe signal handling

Post by Marc Rochkin » Sun, 15 Jun 2003 06:33:43




Quote:> Hello,

> After reading W. R. Stevens' APUE, UNPv1, this group's FAQ and related
> posts, and various web pages... my head is spinning. :o(
> I'm still not sure what would be considered portable and safe signal
> handling in my app described below:

> - My app does not directly call any pthread functions. However, it is
> linked with the pthread library since a 3rd party vendor's library I link
> with is threaded. Actually, in my Makefile, I do use "-mt" and "-
> lpthread". Does this matter (don't know but wanted to mention it in
> case it does)?

It matters in the sense that if somewhere another thread is started, there
are then at least two threads: The initial thread, where your own code
executes, and the other thread(s).

Quote:

> - I've installed the same signal handler function for SIGTERM, SIGQUIT,
> SIGINT, and SIGABRT. I want to catch these in order to call fclose(),
> free(), and exit(). I've included each of these in a single function that
> I'd like to call after receiving one of the signals mentioned
> above.

Those three functions aren't async signal safe, and should not be called in
(or from) a signal handler, as the state of internal structures they use is
indeterminant when such a signal arrives (except under very restricted
circumstances).

Quote:

> - I have a critical section of code that I'd like to make sure isn't
> interrupted or is performed atomically. It's basically a file copy
> (fread(), fwrite()) section that I'd like to either succeed or fail as
> one unit... not be interrupted in the middle of the file copy.

No way to do this that I can think of without the cooperation of all
threads in using the same mutex.

Quote:

> - I call sleep() for a user-defined amount of time (currently 30 seconds)
> after the app's main loop (for(;;)) completes before looping
> again.

> Here's what I have currently:

> 1) I'm using WRS' "Signal()" and "signal()" functions, which use
> sigaction(), verbatim from his UNPv1 text. Should I still use this in
> 2003? Or is it considered outdated and/or unnecessary? Should I instead
> just call sigaction()?

Don't know.

Quote:

> 2) Should I use the example from APUE's signals chapter where he talks
> about using sigsuspend() to protect my critical file copy code section
> from interruption?

I think the example uses it to protect from interruption by signals. It
doesn't protect from interruption by other things. (By "interruption" I
assume you mean giving up the CPU for another thread or for a signal
handler, not an "interrupted system call." Sorry if I've misunderstood.)

Quote:

> 3) Do most UNIX releases nowadays support queued signals? How does this
> contrast with asynchronous signals? Are these terms synonymous?

I don't know about "most." Some do, but they are not required to support
queuing for other than the new realtime signals.

The terms aren't synonymous.

Quote:

> 4) For reliability and safety reasons, do I need to implement some form
> of signal checking that calls select() and then checks a pipe after an
> arrived signal? This was discussed in another post to this group. I don't
> know if doing this is applicable in all situations or not.

It's a way of transforming the event of an arriving signal into a event
represented by a file descriptor, so you can merge it into a select that
may be there to wait on other things. Also, writing to a pipe with write is
async signal safe. Whether this is advantageous depends on the specifics of
what else the code is doing.

Quote:

> Any help, suggestions or guidance would be most appreciated. I'm having
> trouble applying all the information I've read recently.

Cleaning up when one of the signals you mention arrives is certainly a
normal thing to want to do, but to be safe you can't do it directly,
usually. Instead, you have to record that the signal arrived and return
from the signal handler, and then check the flag or pipe or whatever later,
outside of the signal handler.

Another idea is to longjmp out of the signal handler but, wonder of
wonders, longjmp (and its variants) isn't async signal safe! So this is not
a good idea.

A completely safe and straightforward way to deal with signals is to use
threading along with the sigwait functions. It pauses until a signal
arrives and tells you what signal it was. Then, any code you execute is
done outside of a signal handler, so none of the restrictions apply. The
catch is, the function blocks, so it makes sense usually only in a thread
dedicated to that purpose.

--Marc

Quote:

> Many thanks,  -Eric


 
 
 

safe signal handling

Post by Valentin Nechaye » Mon, 16 Jun 2003 14:59:59


EL> - My app does not directly call any pthread functions. However, it
EL> is linked with the pthread library since a 3rd party vendor's library
EL> I link with is threaded. Actually, in my Makefile, I do use "-mt" and
EL> "-lpthread". Does this matter (don't know but wanted to mention it in
EL> case it does)?

If third-party library really uses threads, than signal can be delivered
in any thread unless the thread explicitly stated it should not be interrupted
(using pthread_sigmask()). As you possibly can't influence to attributes
of threads in this application, you're screwed unless special measures
are provided to work with this conditions. For example, you must be ready
to work when two threads execute signal handlers simultaneously.

EL> - I've installed the same signal handler function for SIGTERM, SIGQUIT,
EL> SIGINT, and SIGABRT. I want to catch these in order to call fclose(),
EL> free(), and exit(). I've included each of these in a single function
EL> that I'd like to call after receiving one of the signals mentioned
EL> above.

Catching SIGABRT is senseless: it can appear only from abort() which has
special meaning in program, and fclose() and free() isn't needed in it.
To catch others, better is to raise flag (of sig_atomic_t type) and check
this flag in main code. (And write anything to signal pipe, if used.)

EL> - I have a critical section of code that I'd like to make sure isn't
EL> interrupted or is performed atomically. It's basically a file copy
EL> (fread(), fwrite()) section that I'd like to either succeed or fail as
EL> one unit... not be interrupted in the middle of the file copy.

Block signals during it using pthread_sigmask().

EL> - I call sleep() for a user-defined amount of time (currently 30
EL> seconds) after the app's main loop (for(;;)) completes before looping
EL> again.

EL> Here's what I have currently:

EL> 1) I'm using WRS' "Signal()" and "signal()" functions, which use
EL> sigaction(), verbatim from his UNPv1 text. Should I still use this in
EL> 2003? Or is it considered outdated and/or unnecessary? Should I instead
EL> just call sigaction()?

If you control these functions, use them.

EL> 2) Should I use the example from APUE's signals chapter where he talks
EL> about using sigsuspend() to protect my critical file copy code section
EL> from interruption?

No. Sigsuspend() is *sleeping*. It doesn't allow file copy during it.;)))
Only block (mask) signals in critical sections and unblock after them.

EL> 3) Do most UNIX releases nowadays support queued signals? How does this
EL> contrast with asynchronous signals? Are these terms synonymous?

Not synonymous; moreover, in Unix signal implementations they are mostly
anthonyms.

EL> 4) For reliability and safety reasons, do I need to implement some form
EL> of signal checking that calls select() and then checks a pipe after an
EL> arrived signal? This was discussed in another post to this group. I
EL> don't know if doing this is applicable in all situations or not.

It's applicable here.

-netch-

 
 
 

1. safe signal handling

Hi,

a few q's about how to safely handle a termination signal ensuring proper
cleanup of the app.
The process in question may receive a TERM signal from a controlling process
at any time during its execution. On reception of this signal it should
terminate as cleanly as possible. Since it's written in C++, it's important
to call the main object's destructor as that one might clean up lock files
or similar stuff.
Since I cannot call this destructor right from the signal handler (it might
do rather complex work including malloc(), free(), X11 calls etc.), I'm a
bit stuck as to which way will work best.
The process has a main select() loop, however there may very well be lengthy
operations between select() calls.

Alternative 1, tried this, seems to work quite okay, but since this applies
to different programs not written by me, I'm not at all sure...

static jmp_buf loopenv;

void sighandler( int signo ) // handler for SIGTERM
{
        longjmp( loopenv, signo );

before main loop:

if ( int signo = setjmp( loopenv ) )
{
        // output "terminating on signal signo"
        // cleanup our stuff
        exit();

Is this longjmp() safe given that the signal might arrive during a malloc()
/ free() call etc. and // cleanup our stuff above might also call those?

Alternative 2, didn't try this one yet:

void sighandler( int ) // handler for SIGTERM
{
        alarm( 5 ); // is this safe to do in a handler?

void alarmhandler( int ) // handler for SIGALRM
{
        raise( SIGKILL ); // is this okay to do?

in main loop, check select()'s return value and if neccessary errno and if
it is EINTR, call the destructor and exit() in the hope it takes less than
five seconds.

Thanks a bunch in advance,
-Malte

2. Cron output redirection problem

3. Solaris 8 threads: If a routine is Async-Signal-Safe is it also thread Safe?

4. blank lines at change of leading character

5. mmap, thread-safe, and signal-safe

6. Newbie Sound Problems

7. Thread-safe and Signal-safe

8. NT dialup & callback

9. Signal handling: signal() vs. sigaction()

10. List of routines safe to use in signals?

11. Is `fprintf' signal-safe?

12. Is this a safe signal handler?

13. Delivery of signals when thread not async safe