[Go to CFHT Home Page] Man Pages
Back to Software Index  BORDER=0Manpage Top Level
    cfht_signal(3) manual page Table of Contents

Name

cfht_signal - block, unblock, install handler, and check for signal event

Synopsis


#include <signal.h>
#include <cfht/cfht.h>
void cfht_signal(int signo, PFV handler);
void cfht_signal_block(int signo);
void cfht_signal_unblock(int signo);
int cfht_signal_exent(int signo);
int cfht_signal_peek(int signo);
libcfht.a

Description


Call cfht_signal() just as you would call signal(), with two arguments
(the signal, and a function pointer to your handler.) 
Unlike regular signal(), cfht_signal() . . .
 (1) behaves the same on platforms by using sigaction() underneath
 (2) installs a default handler if you pass CFHT_SIG_TRAP as the handler
 (3) always reinstalls -- remove with cfht_signal(SIGXYZ, CFHT_SIG_DFL);
 (4) always causes system calls to be interrupted (check for EINTR!)
 (5) always runs a SIGCHLD handler also when a child is stopped (^Z-ed)
 (6) always blocks further signals of the same type while in the handler
     (if you must raise the signal from its handler, cfht_signal_unblock
      after the raise call in the handler.)
 (7) returns nothing (See "RETURN VALUE" below.)
Look in the WARNINGS section below for tips on how to deal with the
above behaviors.
Use cfht_signal_block() to start blocking a particular signal.  As
long as the signal is blocked, caught signals will be queued up.
(But you can only determine whether a signal happened, and not how
many times it might have happened.)  If you actually want to DISCARD
signals, use cfht_signal(signo, CFHT_SIG_IGN).
Use cfht_signal_unblock() to allow the handler for a signal to run
again.  If and events are queued up, the handler will run before
cfht_signal_unblock() even returns to the routine that called it.
IF YOU PASSED CFHT_SIG_TRAP FOR THE HANDLER ARGUMENT IN cfht_signal(),
then you can use cfht_signal_peek() to check if that signal has
occurred, or you can use cfht_signal_event() to check if the signal
occurred since the last time you looked.  That is, cfht_signal_event()
resets the flag, while cfht_signal_peek() does not.

Return Value


There is no return code from cfht_signal() because signal() calls can
only really fail if you pass a bogus signal number.  In this rare case,
cfht_signal will log a CFHT_WARN message itself, if it ever happens.

Warnings


Signals that occur close together may only result in a single run of
your handler.  You cannot reliably count the number of times that a
signal occurred in unix.
If you absolutely must have a handler that gets installed in one-shot
mode instead, then you’ll have to call sigaction() yourself, with
SA_RESETHAND flag set.  Use of this flag reverses both (3) AND (6)
in the DESCRIPTION above.
If you absolutely must have system calls that re-start, you can try
using a macro like the one described in the following clip from the
glibc info pages, TEMP_FAILURE_RETRY().  Wrap all system calls that
might be interrupted in this macro.  Note that even with this, you
still have to check for read()’s that are interrupted, since they
could return less than the number of bytes you told them to read!
(In BSD, even this would re-start for you.)  If TEMP_FAILURE_RETRY()
is enough, then include <cfht/cfht.h> and use it as described below.
Here’s what the glibc pages say about TEMP_FAILURE_RETRY:
=======================================================================
   POSIX specifies one approach: make the primitive fail right away. 
The error code for this kind of failure is ‘EINTR’.  This is flexible,
but usually inconvenient.  Typically, POSIX applications that use signal
handlers must check for ‘EINTR’ after each library function that can
return it, in order to try the call again.  Often programmers forget to
check, which is a common source of error.
  The GNU library provides a convenient way to retry a call after a
temporary failure, with the macro ‘TEMP_FAILURE_RETRY’:
 -- Macro: TEMP_FAILURE_RETRY (EXPRESSION)
     This macro evaluates EXPRESSION once.  If it fails and reports
     error code ‘EINTR’, ‘TEMP_FAILURE_RETRY’ evaluates it again, and
     over and over until the result is not a temporary failure.
     The value returned by ‘TEMP_FAILURE_RETRY’ is whatever value
     EXPRESSION produced.
  BSD avoids ‘EINTR’ entirely and provides a more convenient approach:
To restart the interrupted primitive, instead of making it fail.  If
you choose this approach, you need not be concerned with ‘EINTR’.
=======================================================================
There is no easy way the get the true BSD behavior that works on all
systems.  Calling sigaction() yourself, with the flag SA_RESTART (and
not SA_INTERRUPT) should work but HP has a different way, so you’ll
also need to hack your handler, and not just the code that installs
the handler.  To reverse behavior (4) in DESCRIPTION, try using code
such as this:
   #include <signal.h>
   void signal_handler(int signo
   #ifdef SIG_RESTART
                       /* need a couple of extra args on HPs */
                       , int code UNUSED, struct sigcontext *scp
   #endif
                       )
   {
       ...signal handler does its stuff here...
   #ifdef SIG_RESTART
       /* if context pointer not NULL, tell the system call to restart
*/
       if (scp!=NULL)
           scp->sc_syscall_action = SIG_RESTART;
   #endif
   }
   main()
   {
       struct sigaction act;
       ...
       act.sa_handler = signal_handler;
       sigemptyset(&act.sa_mask);
   #ifdef SA_RESTART
       /*
        * This is the code that gets compiled on Solaris machines.
        * There’s no need for the extra code in the handler since
        * this here flag does the job.
        */
       act.sa_flags = SA_RESTART;
   #else
       /*
        * If SA_RESTART is undefined, and if SIG_RESTART is undefined,
        * we are probably already on a BSD system where the defaults
        * are correct for re-starting system calls.
        */
       act.sa_flags = 0;
   #endif  
       sigaction(SIGUSR1,&act,0);
       ...
   }
Of course if you can figure out a way to do it by just using the
defaults that cfht_signal() gives, that’s much better.

See Also

sigaction(2) , sigsetops(3C) , signal(5) , sigvector(2) , and the section on signals in the glibc info pages at the URL http://rpm/INFO2WWW/info2www.cgi?(libc.info)Signal%20Handling


Table of Contents