00001 00002 // Copyright (C) 1999--2001 Petter Urkedal (petter.urkedal@matfys.lth.se) 00003 // 00004 // This file is free software; you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation; either version 2 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // This file is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with this program; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 // 00018 // As a special exception, you may use this file as part of a free 00019 // software library without restriction. Specifically, if other files 00020 // instantiate templates or use macros or inline functions from this 00021 // file, or you compile this file and link it with other files to 00022 // produce an executable, this file does not by itself cause the 00023 // resulting executable to be covered by the GNU General Public 00024 // License. This exception does not however invalidate any other 00025 // reasons why the executable file might be covered by the GNU General 00026 // Public License. 00027 // 00028 // $Id: signal.h,v 1.1 2002/05/30 18:01:37 petter_urkedal Exp $ 00029 00030 00031 00032 #ifndef MORE_CF_SIGNAL_H 00033 #define MORE_CF_SIGNAL_H 00034 00035 #include <exception> 00036 #include <csignal> 00037 00038 #define MORE_CF_POINTCHECKER_COUNT_MAX 64 00039 00040 00041 00042 namespace more { 00043 namespace cf { 00044 00045 ///\if bits 00046 namespace bits { 00047 extern int pending_signal; 00048 00049 extern void (*pointcheckers[MORE_CF_POINTCHECKER_COUNT_MAX])(); 00050 extern int n_pointcheckers; 00051 00052 void dispatch_signal(); 00053 } 00054 ///\endif 00055 00056 /** Exception to be thrown upon signals. This exception is thrown 00057 by pointchecker after a signal is raised which was earlier 00058 registered to be handled by calling handle_signal. This 00059 exception is subclassed for a few selected signals. */ 00060 struct signal_raised : std::exception 00061 { 00062 explicit signal_raised(int i) : m_signo(i) {} 00063 00064 int which() const { return m_signo; } 00065 00066 virtual char const* what() const throw(); 00067 00068 private: 00069 int m_signo; 00070 }; 00071 00072 /** Exception to be thrown upon SIGINT. */ 00073 struct sigint_raised : signal_raised { sigint_raised(); }; // SIGINT 00074 00075 /** Exception to be thrown upon SIGFPE. */ 00076 struct sigfpe_raised : signal_raised { sigfpe_raised(); }; // SIGFPE 00077 00078 /** Exception to be thrown upon SIGALRM. */ 00079 struct sigalrm_raised : signal_raised { sigalrm_raised(); }; // SIGALRM 00080 00081 /** Exception to be thrown upon SIGSEGV. */ 00082 struct sigsegv_raised : signal_raised { sigsegv_raised(); }; // SIGSEGV 00083 00084 #if defined(MORE_BACKWARD) && MORE_BACKWARD < 20010522 00085 typedef sigint_raised program_interrupt; 00086 typedef sigfpe_raised float_error; 00087 typedef sigalrm_raised timeout; 00088 typedef sigsegv_raised segmentation_fault; 00089 #endif 00090 00091 /** Check for signals, thread cancels and such at this point. The 00092 actual code that is run by checkpoint is registered with 00093 register_pointchecker. It is typically used to throw exceptions 00094 upon signals or thread cancel. */ 00095 inline void 00096 checkpoint() 00097 { 00098 if (bits::pending_signal) 00099 bits::dispatch_signal(); 00100 for(int i = 0; i < bits::n_pointcheckers; ++i) 00101 bits::pointcheckers[i](); 00102 } 00103 00104 /** Register a function to be run by checkpoint. It is important to 00105 the efficiency to keep the number of registered pointcheckers at 00106 an absolute minimum, as checkpoint must call them all. 00107 Therefore, the intention is that each library using libmore 00108 registers only one pointchecker if reeded, and does all checks 00109 there. There is an arbitrary limit of to the number of 00110 pointcheckers that can be registered, and an exception is thrown 00111 if this limit is exceeded. */ 00112 void register_pointchecker(void (*)()); 00113 00114 /** Unregister a function registered by register_pointchecker. */ 00115 void unregister_pointchecker(void (*)()); 00116 00117 /** Install a pointchecker to throw an exception upon the signal \a sig. */ 00118 void handle_signal(int sig); 00119 00120 /** Handle \c SIGINT so that it does not quit the program at once 00121 but allows the application to clean up. After the first \c 00122 SIGINT, a message is printed to the screen saying that CTRL-C 00123 must be pressed once more for immediate termination, and that is 00124 what happens if the program receives another \c SIGINT. If 00125 checkpoint() is called before that, an exception is thrown, 00126 giving the application a chance to make a breathtaking exit. */ 00127 void enable_delayed_interrupt(); 00128 00129 /** Handle the signal that will cause \a xc to be thrown. */ 00130 template<typename SignalException> 00131 void handle_signal(SignalException const& xc) 00132 { 00133 handle_signal(xc.which()); 00134 } 00135 00136 }} // more::cf 00137 00138 #endif