ASSA::SigHandlers Class Reference

#include <SigHandlers.h>

Inheritance diagram for ASSA::SigHandlers:

ASSA::SigHandler List of all members.

Public Member Functions

virtual int install (int signum_, EventHandler *new_hand_, SigAction *new_disp_=0, EventHandler **old_hand_=0, SigAction *old_disp_=0)
 Register EventHandler with dispatching system.
virtual int remove (int signum_, EventHandler *eh_, SigAction *new_disp_=0, SigAction *old_disp_=0)
 Remove EventHandler from the list of registered handler for signum_.

Static Public Member Functions

static void sighandlers_dispatcher (int signum_)
 A wrapper around static SigHandlers::dispatch().

Static Private Member Functions

static void dispatch (int signum_)
 The heart of SigHandlers class - this callback function is really registered with OS to catch all of the signals for which event handler has been installed.

Detailed Description

Definition at line 53 of file SigHandlers.h.


Member Function Documentation

void SigHandlers::dispatch int  signum_  )  [static, private]
 

The heart of SigHandlers class - this callback function is really registered with OS to catch all of the signals for which event handler has been installed.

Appropriate EventHandler(s) are then notified.

Reimplemented from ASSA::SigHandler.

Definition at line 235 of file SigHandlers.cpp.

References ASSA::SigHandlersList::begin(), ASSA::SigHandlersList::end(), ASSA::SigHandlersList::erase(), ASSA::SigHandlersList::instance(), ASSA::SIGHAND, and trace_with_mask.

Referenced by sighandlers_dispatcher().

00236 {
00237     trace_with_mask("SigHandlers::dispatch", SIGHAND);
00238 
00239     /*---
00240       For every element in the set that holds all EventHandlers for
00241       given signum, call its respective handle_signal() member function.
00242       ---*/
00243 
00244     /*--- save errno ---*/
00245     int errno_saved = errno;
00246 
00247     SigHandlersList& handlist = *(SigHandlersList::instance(signum_));
00248     SigHandlersList::iterator it;
00249     EventHandler* ehp;
00250     
00251     for (it=handlist.begin(); it != handlist.end(); it++) {
00252         ehp = *it;
00253         if (ehp->handle_signal (signum_) == -1) {
00254             /*---
00255               this event handler reported error when handling
00256               signum - remove it from the set
00257               ---*/
00258             handlist.erase (it);
00259         }
00260     }
00261     /*--- restore errno ---*/
00262     errno = errno_saved;
00263 }

int SigHandlers::install int  signum_,
EventHandler new_hand_,
SigAction new_disp_ = 0,
EventHandler **  old_hand_ = 0,
SigAction old_disp_ = 0
[virtual]
 

Register EventHandler with dispatching system.

Parameters:
signum_ (In ) Signal number.
new_hand_ (In ) Pointer to new event handler to install.
new_disp_ (In=0 ) New disposition to use to handle signal.
old_hand_ (Out=0) Placeholder for old event handler.
old_disp_ (Out=0) Placeholder for old disposition.
Returns:
0 on success; -1 on error.

Reimplemented from ASSA::SigHandler.

Definition at line 34 of file SigHandlers.cpp.

References ASSA::SigHandlersList::cfunc_handler(), DL, EL, ASSA::ERROR, ASSA::SigAction::handler(), ASSA::SigHandler::in_range(), ASSA::SigHandlersList::insert(), ASSA::SigHandlersList::instance(), ASSA::SigAction::retrieve_action(), ASSA::SIGHAND, sighandlers_dispatcher(), and trace_with_mask.

00039 {
00040     /*
00041       Retrieve current signal disposition. If 3rd party handler has 
00042       already been istalled, make CFUNC_Handler out of it, and put it in 
00043       the list with id=0. 
00044       
00045       Add new_hand_ to the list. Has global sighandlers_dispatcher not 
00046       been installed yet, install it too.
00047     */
00048 
00049     trace_with_mask("SigHandlers::install()", SIGHAND);
00050 
00051     if (!in_range(signum_) == -1) {
00052         EL((ERROR,"in_range (%s) failed\n",signum_));
00053         return -1;
00054     }
00055 
00056     CFUNC_Handler* cfhp = NULL;
00057     SigHandlersList* handlist = NULL;
00058 
00059     handlist = SigHandlersList::instance(signum_);
00060 
00061     /*--- Retrieve current signal disposition ---*/
00062 
00063     SigAction cd;
00064     cd.retrieve_action(signum_);
00065 
00066     /*
00067       Check whether 3rd party software has already installed 
00068       signal handler. 
00069     */
00070     if ( cd.handler() != (C_SIG_HANDLER) sighandlers_dispatcher &&
00071          cd.handler() != SIG_IGN && 
00072          cd.handler() != SIG_DFL ) 
00073     {
00074     /*
00075       Looks like some other code got ahead of me and installed C-function 
00076       signal handler. Make a note of it.  
00077       
00078       Create EventHandler to hold 3rd party handler. This handler will be 
00079       deleted only by SigHandlers::remove (NULL), when application demanded 
00080       to remove all of the handlers.
00081     */
00082         DL((SIGHAND,"Detected 3rd party \"C\" handler!\n"));
00083         
00084         cfhp = new CFUNC_Handler (cd.handler ());
00085         handlist->cfunc_handler (cfhp);
00086         
00087         /*
00088           Insert 3rd party handler in list of handlers 
00089           for this signal.
00090         */
00091         DL((SIGHAND,"Adding 3rd party \"C\" handler\n"));
00092         
00093         if ( handlist->insert (cfhp) == false ) {
00094             EL((ERROR, "Failed to insert "\
00095                 "c_func_handler for signum %d\n", signum_));
00096             delete (cfhp);
00097             handlist->cfunc_handler (0);
00098             return -1;
00099         }
00100         DL((SIGHAND,"Set size: %d\n", handlist->size () ));
00101     }
00102     /*--- Add new_hand_ to the list of handlers for signum_. ---*/
00103     
00104     DL((SIGHAND,"Adding EventHandler to the list\n"));
00105 
00106     if (handlist->insert (new_hand_) == false) {
00107         /*---
00108           I failed to install new handler and might have already
00109           added 3rd party CFUNC_Handler to the list without altering
00110           disposition - if that's true, clean up the list.
00111           ---*/
00112         EL((ERROR,"failed to add new_hand_ to handlers list\n"));
00113 
00114         if (handlist->seen_cfunc_handler () &&
00115             handlist->size() == 1) 
00116         {
00117             handlist->erase ();
00118             handlist->cfunc_handler (0);
00119         }
00120         return -1;
00121     }
00122     DL((SIGHAND,"Set size: %d\n", handlist->size () ));
00123 
00124     /*--- Has sighandlers_dispatcher been already installed? ---*/
00125 
00126     if (cd.handler() == (C_SIG_HANDLER) sighandlers_dispatcher) {
00127         return 0;
00128     }
00129     DL((SIGHAND,"Installing 'sighandlers_dispatcher'\n"));
00130 
00131     /*
00132       Installing new disposition; if user forgot to give me one
00133       then default will be used. 
00134     */
00135     SigAction sa ((C_SIG_HANDLER) SIG_DFL);
00136 
00137     if (new_disp_ == 0) {
00138         new_disp_ = &sa;
00139     }
00140     
00141     new_disp_->handler ((C_SIG_HANDLER) sighandlers_dispatcher);
00142         
00143     if (new_disp_->register_action (signum_, old_disp_) == -1) {
00144         /*---
00145           I failed to install sighandlers_dispatcher. Up to this
00146           point, if application had conventional C handler installed,
00147           it still remains active. Handlers list built so far is
00148           meaningless - get rid of it. ---*/
00149         
00150         EL((ERROR,"register_action() error\n"));
00151         
00152         if (handlist->seen_cfunc_handler ()) {
00153             handlist->erase ();
00154             handlist->cfunc_handler (0);
00155             delete cfhp;
00156         }
00157         handlist->erase (new_hand_);
00158         return -1;
00159     }
00160     return 0;
00161 }

int SigHandlers::remove int  signum_,
EventHandler eh_,
SigAction new_disp_ = 0,
SigAction old_disp_ = 0
[virtual]
 

Remove EventHandler from the list of registered handler for signum_.

If eh_ is NULL, then all EventHandler(s) will be removed from the list, and object will go back to passive mode in which no signal handling is done via SigHandlers class dispatcher. If new_disp_ is omitted, SIG_DFL will be used instead.

Parameters:
signum_ (In ) Signal number.
eh_ (In ) Event handler to remove.
new_disp_ (In=0 ) New disposition to use to handle signal.
old_disp_ (Out=0) Placeholder for old disposition.
Returns:
0 on success; -1 on error.

Reimplemented from ASSA::SigHandler.

Definition at line 165 of file SigHandlers.cpp.

References DL, EL, ASSA::SigHandlersList::end(), ASSA::SigHandlersList::erase(), ASSA::ERROR, ASSA::SigHandlersList::find(), ASSA::SigHandler::in_range(), ASSA::SigHandlersList::instance(), ASSA::SIGHAND, ASSA::SigHandlersList::size(), and trace_with_mask.

00168 {
00169     trace_with_mask("SigHandlers::remove()", SIGHAND);
00170 
00171     if (in_range (signum_)) {
00172         EL((ERROR, "singum_ %d is out of range\n", signum_));
00173         return -1;
00174     }
00175 
00176     CFUNC_Handler* Cfhp = NULL; // pointer to C-function event handler
00177     EventHandler* ehp = NULL;   // pointer to current event handler
00178 
00179     SigHandlersList& handlist = *(SigHandlersList::instance(signum_));
00180     
00181     if (eh_ == NULL) {
00182         DL((SIGHAND,"Erasing the entire set\n"));
00183         /*--- Erase an entire list. ---*/
00184         handlist.erase ();
00185         DL((SIGHAND,"Set size: %d\n", handlist.size ()));
00186     }
00187     else {
00188         /*
00189           Note: I cannot do erasure in the same loop for following  reason:
00190           
00191           According to Stroustrup (Section 17.4.1.7):
00192           "After erase(), the iterator cannot be used again because
00193           the element to which it pointed is no longer there."
00194           
00195           According to STL Tutorial and Ref. Guide:
00196           "The erase function invalidates all iterators to all
00197           positions past the point of erasure."
00198           
00199           That's why here we first take care of id recycling and heap memory 
00200           deallocation, and only then clean() the map all at once.
00201         */
00202         SigHandlersList::iterator it;
00203         
00204         if ((it = handlist.find (eh_)) != handlist.end ()) {
00205             DL((SIGHAND,"Removing EventHandler\n"));
00206             ehp = (*it);
00207             handlist.erase (it);
00208         }
00209         DL((SIGHAND,"Set size: %d\n", handlist.size () ));
00210     }
00211     /*--- If set is not empty, we're done ---*/
00212     if (handlist.size ()) return 0;
00213 
00214     /* If map was emptied out, install new disposition
00215        with the 3rd party "C" function handler, if we had it.
00216     */
00217     SigAction null_sa;
00218     if (new_disp_ == 0) new_disp_ = &null_sa;
00219 
00220     DL((SIGHAND,"Handlers List is empty\n"));
00221     
00222     if (handlist.seen_cfunc_handler ()) {
00223         /*--- Put 3rd party handler into disposition  ---*/
00224         DL((SIGHAND,"Reinstalling \"C\" handler\n"));
00225         Cfhp = handlist.cfunc_handler (0);
00226         new_disp_->handler (Cfhp->handler ());
00227         delete Cfhp;
00228     }
00229     /*--- Install new disposition ---*/
00230     return new_disp_->register_action (signum_, old_disp_);
00231 }

void SigHandlers::sighandlers_dispatcher int  signum_  )  [static]
 

A wrapper around static SigHandlers::dispatch().

It is needed for the purpose of differentiation it with other signal handlers that might be installed by user's code.

Parameters:
signum_ Dispatch event handlers for this signal.

Definition at line 24 of file SigHandlers.cpp.

References dispatch(), DL, ASSA::SIGHAND, and trace_with_mask.

Referenced by install().

00025 {
00026     trace_with_mask("SigHandlers::sighandlers_dispatch", SIGHAND);
00027 
00028     DL((SIGHAND,"==> Recevied signal # %d\n", signum_));
00029     dispatch (signum_);
00030 }


The documentation for this class was generated from the following files:
Generated on Mon Dec 19 16:20:19 2005 for libassa by  doxygen 1.4.5