00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "assa/SigHandlers.h"
00013
00014 using namespace ASSA;
00015
00016
00017
00018
00019
00020 SigHandlersList* SigHandlersList::m_instance[NSIG];
00021
00022 void
00023 SigHandlers::
00024 sighandlers_dispatcher (int signum_)
00025 {
00026 trace_with_mask("SigHandlers::sighandlers_dispatch", SIGHAND);
00027
00028 DL((SIGHAND,"==> Recevied signal # %d\n", signum_));
00029 dispatch (signum_);
00030 }
00031
00032 int
00033 SigHandlers::
00034 install (int signum_,
00035 EventHandler* new_hand_,
00036 SigAction* new_disp_,
00037 EventHandler** old_hand_,
00038 SigAction* old_disp_)
00039 {
00040
00041
00042
00043
00044
00045
00046
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
00062
00063 SigAction cd;
00064 cd.retrieve_action(signum_);
00065
00066
00067
00068
00069
00070 if ( cd.handler() != (C_SIG_HANDLER) sighandlers_dispatcher &&
00071 cd.handler() != SIG_IGN &&
00072 cd.handler() != SIG_DFL )
00073 {
00074
00075
00076
00077
00078
00079
00080
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
00089
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
00103
00104 DL((SIGHAND,"Adding EventHandler to the list\n"));
00105
00106 if (handlist->insert (new_hand_) == false) {
00107
00108
00109
00110
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
00125
00126 if (cd.handler() == (C_SIG_HANDLER) sighandlers_dispatcher) {
00127 return 0;
00128 }
00129 DL((SIGHAND,"Installing 'sighandlers_dispatcher'\n"));
00130
00131
00132
00133
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
00146
00147
00148
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 }
00162
00163 int
00164 SigHandlers::
00165 remove (int signum_, EventHandler* eh_,
00166 SigAction* new_disp_, SigAction* old_disp_)
00167
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;
00177 EventHandler* ehp = NULL;
00178
00179 SigHandlersList& handlist = *(SigHandlersList::instance(signum_));
00180
00181 if (eh_ == NULL) {
00182 DL((SIGHAND,"Erasing the entire set\n"));
00183
00184 handlist.erase ();
00185 DL((SIGHAND,"Set size: %d\n", handlist.size ()));
00186 }
00187 else {
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
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
00212 if (handlist.size ()) return 0;
00213
00214
00215
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
00224 DL((SIGHAND,"Reinstalling \"C\" handler\n"));
00225 Cfhp = handlist.cfunc_handler (0);
00226 new_disp_->handler (Cfhp->handler ());
00227 delete Cfhp;
00228 }
00229
00230 return new_disp_->register_action (signum_, old_disp_);
00231 }
00232
00233 void
00234 SigHandlers::
00235 dispatch (int signum_)
00236 {
00237 trace_with_mask("SigHandlers::dispatch", SIGHAND);
00238
00239
00240
00241
00242
00243
00244
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
00256
00257
00258 handlist.erase (it);
00259 }
00260 }
00261
00262 errno = errno_saved;
00263 }