libassa 3.5.0
|
00001 // -*- c++ -*- 00002 //--------------------------------------------------------------------------- 00003 // SigHandler.cpp 00004 //--------------------------------------------------------------------------- 00005 // Copyright (C) 1997-2002 Vladislav Grinchenko 00006 // 00007 // This library is free software; you can redistribute it and/or 00008 // modify it under the terms of the GNU Library General Public 00009 // License as published by the Free Software Foundation; either 00010 // version 2 of the License, or (at your option) any later version. 00011 //--------------------------------------------------------------------------- 00012 #include <signal.h> 00013 00014 #include "assa/Assure.h" 00015 #include "assa/SigHandler.h" 00016 00017 using namespace ASSA; 00018 00019 #if !defined(WIN32) 00020 00021 /*--- static variables ---*/ 00022 00023 EventHandler* SigHandler::m_signal_handlers [NSIG]; 00024 00025 int 00026 SigHandler:: 00027 in_range (int signum_) 00028 { 00029 trace_with_mask("SigHandler::in_range", SIGHAND); 00030 00031 if ( signum_ >= 1 && signum_ < NSIG) { 00032 return 0; 00033 } 00034 else { 00035 DL((SIGHAND,"signum_ %d is out of range [1;%d]\n", NSIG)); 00036 return -1; 00037 } 00038 } 00039 00040 EventHandler * 00041 SigHandler:: 00042 handler (int signum_, EventHandler* newh_) 00043 { 00044 trace_with_mask("SigHandler::handler(int, EH*)", SIGHAND); 00045 00046 00047 if (in_range(signum_) == -1) 00048 return 0; 00049 00050 EventHandler* oh = m_signal_handlers[signum_]; 00051 m_signal_handlers[signum_] = newh_; 00052 00053 return oh; 00054 } 00055 00056 EventHandler * 00057 SigHandler:: 00058 handler (int signum_) 00059 { 00060 trace_with_mask("SigHandler::handler", SIGHAND); 00061 00062 if ( in_range (signum_) == -1 ) 00063 return 0; 00064 00065 return m_signal_handlers[signum_]; 00066 } 00067 00068 int 00069 SigHandler:: 00070 install (int signum_, EventHandler *new_hand_, SigAction *new_disp_, 00071 EventHandler **old_hand_, SigAction *old_disp_) 00072 { 00073 trace_with_mask("SigHandler::install", SIGHAND); 00074 00075 if (in_range (signum_) == -1) 00076 return -1; 00077 00078 /*--- replace old Event Handler ptr with new one in my internal 00079 dispatch table, returning the old one. 00080 ---*/ 00081 EventHandler* eh = handler(signum_, new_hand_); 00082 00083 /*--- if I am given place to store, save old handler ---*/ 00084 if (old_hand_ != 0) 00085 *old_hand_ = eh; 00086 00087 /*--- retrieve old disposition ---*/ 00088 if (old_disp_ != 0) { 00089 old_disp_->retrieve_action (signum_); 00090 old_disp_->handler ((C_SIG_HANDLER) SIG_DFL); 00091 } 00092 00093 /*--- if new disposition is NULL, use null action instead ---*/ 00094 SigAction null_sa; 00095 00096 if (new_disp_ == 0) 00097 new_disp_ = &null_sa; 00098 00099 /*--- install my dispatcher ---*/ 00100 new_disp_->handler((C_SIG_HANDLER) SigHandler::dispatch); 00101 00102 return new_disp_->register_action(signum_, old_disp_); 00103 } 00104 00105 int 00106 SigHandler:: 00107 remove (int signum_, EventHandler* /* eh_ */, 00108 SigAction *new_disp_, SigAction *old_disp_) 00109 { 00110 trace_with_mask("SigHandler::remove", SIGHAND); 00111 00112 if (in_range(signum_) == -1) 00113 return -1; 00114 /*--- 00115 We need default disposition here if user forgot to give us one. 00116 ---*/ 00117 SigAction sa ((C_SIG_HANDLER) SIG_DFL); 00118 00119 if (new_disp_ == 0) { 00120 new_disp_ = &sa; 00121 } 00122 00123 m_signal_handlers[signum_] = 0; 00124 00125 return new_disp_->register_action (signum_, old_disp_); 00126 } 00127 00128 void 00129 SigHandler:: 00130 dispatch (int signum_) 00131 { 00132 trace_with_mask("SigHandler::dispatch", SIGHAND); 00133 00134 /*--- save errno ---*/ 00135 int my_errno = errno; 00136 00137 EventHandler *eh = m_signal_handlers[signum_]; 00138 00139 if (eh != 0 && eh->handle_signal(signum_) == -1) { 00140 /*--- 00141 we are in trouble, fall back to defaults 00142 ---*/ 00143 SigAction defact((C_SIG_HANDLER) SIG_DFL); 00144 m_signal_handlers[signum_] = 0; 00145 defact.register_action(signum_); 00146 } 00147 /*--- restore errno ---*/ 00148 errno = my_errno; 00149 } 00150 00151 #endif // !defined(WIN32) 00152