Signal.cpp

Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of the GNU General Public License as published by
00004  * the Free Software Foundation; either version 3 of the License, or
00005  * (at your option) any later version.
00006  *
00007  * Written (W) 1999-2009 Soeren Sonnenburg
00008  * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
00009  */
00010 
00011 #include "lib/config.h"
00012 
00013 #ifndef WIN32
00014 
00015 #include <stdlib.h>
00016 #include <signal.h>
00017 #include <string.h>
00018 
00019 #include "lib/io.h"
00020 #include "lib/Signal.h"
00021 
00022 int CSignal::signals[NUMTRAPPEDSIGS]={SIGINT, SIGURG};
00023 struct sigaction CSignal::oldsigaction[NUMTRAPPEDSIGS];
00024 bool CSignal::active=false;
00025 bool CSignal::cancel_computation=false;
00026 bool CSignal::cancel_immediately=false;
00027 
00028 CSignal::CSignal()
00029 : CSGObject()
00030 {
00031 }
00032 
00033 CSignal::~CSignal()
00034 {
00035     if (!unset_handler())
00036         SG_PRINT("error uninitalizing signal handler\n");
00037 }
00038 
00039 void CSignal::handler(int signal)
00040 {
00041     if (signal == SIGINT)
00042     {
00043         SG_SPRINT("\nImmediately return to prompt / Prematurely finish computations / Do nothing (I/P/D)? ");
00044         char answer=fgetc(stdin);
00045 
00046         if (answer == 'I')
00047         {
00048             unset_handler();
00049             set_cancel(true);
00050             if (sg_print_error)
00051                 sg_print_error(stdout, "sg stopped by SIGINT\n");
00052         }
00053         else if (answer == 'P')
00054             set_cancel();
00055         else
00056             SG_SPRINT("Continuing...\n");
00057     }
00058     else if (signal == SIGURG)
00059         set_cancel();
00060     else
00061         SG_SPRINT("unknown signal %d received\n", signal);
00062 }
00063 
00064 bool CSignal::set_handler()
00065 {
00066     if (!active)
00067     {
00068         struct sigaction act;
00069         sigset_t st;
00070 
00071         sigemptyset(&st);
00072         for (int32_t i=0; i<NUMTRAPPEDSIGS; i++)
00073             sigaddset(&st, signals[i]);
00074 
00075 #ifndef __INTERIX
00076         act.sa_sigaction=NULL; //just in case
00077 #endif
00078         act.sa_handler=CSignal::handler;
00079         act.sa_mask = st;
00080         act.sa_flags = 0;
00081 
00082         for (int32_t i=0; i<NUMTRAPPEDSIGS; i++)
00083         {
00084             if (sigaction(signals[i], &act, &oldsigaction[i]))
00085             {
00086                 SG_SPRINT("Error trapping signals!\n");
00087                 for (int32_t j=i-1; j>=0; j--)
00088                     sigaction(signals[i], &oldsigaction[i], NULL);
00089 
00090                 clear();
00091                 return false;
00092             }
00093         }
00094 
00095         active=true;
00096         return true;
00097     }
00098     else
00099         return false;
00100 }
00101 
00102 bool CSignal::unset_handler()
00103 {
00104     if (active)
00105     {
00106         bool result=true;
00107 
00108         for (int32_t i=0; i<NUMTRAPPEDSIGS; i++)
00109         {
00110             if (sigaction(signals[i], &oldsigaction[i], NULL))
00111             {
00112                 SG_SPRINT("error uninitalizing signal handler for signal %d\n", signals[i]);
00113                 result=false;
00114             }
00115         }
00116 
00117         if (result)
00118             clear();
00119 
00120         return result;
00121     }
00122     else
00123         return false;
00124 }
00125 
00126 void CSignal::clear_cancel()
00127 {
00128     cancel_computation=false;
00129     cancel_immediately=false;
00130 }
00131 
00132 void CSignal::set_cancel(bool immediately)
00133 {
00134     cancel_computation=true;
00135 
00136     if (immediately)
00137         cancel_immediately=true;
00138 }
00139 
00140 void CSignal::clear()
00141 {
00142     clear_cancel();
00143     active=false;
00144     memset(&CSignal::oldsigaction, 0, sizeof(CSignal::oldsigaction));
00145 }
00146 #endif //WIN32

SHOGUN Machine Learning Toolbox - Documentation