1 /*
2  *  Portable Agile C++ Classes (PACC)
3  *  Copyright (C) 2004 by Marc Parizeau
4  *  http://manitou.gel.ulaval.ca/~parizeau/PACC
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2.1 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  Contact:
21  *  Laboratoire de Vision et Systemes Numeriques
22  *  Departement de genie electrique et de genie informatique
23  *  Universite Laval, Quebec, Canada, G1K 7P4
24  *  http://vision.gel.ulaval.ca
25  *
26  */
27 
28 /*!
29  * \file PACC/Util/SignalHandler.hpp
30  * \brief Class definition for the portable signal handler.
31  * \author Marc Dubreuil and Christian Gagne, Laboratoire de vision et systèmes numériques, Université Laval
32  * $Revision: 1.5.2.1 $
33  * $Date: 2007/09/10 18:24:10 $
34  */
35 
36 #ifndef PACC_SIGNALHANDLER_HPP
37 #define PACC_SIGNALHANDLER_HPP
38 
39 #include <stack>
40 #include <signal.h>
41 
42 namespace PACC {
43 
44 	using namespace std;
45 
46 	/*!
47 	 *  \brief Portable signal handling.
48 	 *  \author Marc Dubreuil, Christian Gagne and Marc Parizeau, Laboratoire de vision et syst&egrave;mes num&eacute;riques, Universit&eacute; Laval
49 	 *  \ingroup Util
50 	 *
51 	 *  This class can be used to handle common signals. To define custom handlers,
52 	 *  it should be subclassed and virtual method SignalHandler::main should be
53 	 *  overloaded. For example, the following code snippet defines a custom
54 	 *  handler for signal SignalType::eSigInt (Ctl-C):
55 \verbatim
56 class SigIntHandler : public SignalHandler {
57  public:
58     SigIntHandler(void) {setCustomAction(eSigInt);}
59 
60     virtual void main(SignalType inType) {
61         switch(inType) {
62            case eSigInt:
63              cout << "My custom handler!" << endl;
64              exit(-1);
65            default:
66              cout << "Unsupported signal!" << endl;
67              break;
68         }
69 	}
70 };
71 \endverbatim
72 Furthermore, for each signal type, a stack of actions can be managed using methods SignalHandler::pushAction and SignalHandler::popAction.
73 	 */
74 	class SignalHandler {
75 	 public:
76 		//! Enumeration of supported signal types.
77 		enum SignalType {
78 			eSigAbrt=0,  //!< Abort (ANSI).
79 			eSigFPE,     //!< Floating-point exception (ANSI).
80 			eSigIll,     //!< Illegal instruction (ANSI).
81 			eSigInt,     //!< Interrupt (ANSI).
82 			eSigSegV,    //!< Segmentation violation (ANSI).
83 			eSigTerm,    //!< Termination (ANSI).
84 			eSigAlrm,    //!< Alarm clock (POSIX).
85 			eSigChld,    //!< Child status has changed (POSIX).
86 			eSigCont,    //!< Continue (POSIX).
87 			eSigHUp,     //!< Hangup (POSIX).
88 			eSigKill,    //!< Kill, unblockable (POSIX).
89 			eSigPipe,    //!< Broken pipe (POSIX).
90 			eSigQuit,    //!< Quit (POSIX).
91 			eSigStop,    //!< Stop, unblockable (POSIX).
92 			eSigTStp,    //!< Keyboard stop (POSIX).
93 			eSigTrap,    //!< Trace trap (POSIX).
94 			eSigTTin,    //!< Background read from tty (POSIX).
95 			eSigTTou,    //!< Background write to tty (POSIX).
96 			eSigUsr1,    //!< User-defined signal 1 (POSIX).
97 			eSigUsr2,    //!< User-defined signal 2 (POSIX).
98 			NSIGNALS
99 		};
100 
101 		//! Construct this signal handler.
SignalHandler(void)102 		SignalHandler(void) {}
103 
104 		//! delete this signal handler.
~SignalHandler(void)105 		virtual ~SignalHandler(void) {}
106 
107 		/*! \brief Main function of signal handler.
108 
109 			This pure virtual method must be overloaded in a subclass in order to
110 			define custom signal actions. Argument \c inType specifies the signal
111 			type that must be processed for the current pending signal.
112 		 */
113 		virtual void main(SignalType inType) = 0;
114 
115 		//! Pop previous action for signals of type \c inType.
116 		static void popAction(SignalType inType);
117 
118 		//! Push current action for signals of type \c inType.
119 		static void pushAction(SignalType inType);
120 
121 		//! Make this signal handler process future signals of type \c inType.
122 		void setCustomAction(SignalType inType);
123 
124 		//! Make the default system action process future signals of type \c inType.
125 		static void setDefaultAction(SignalType inType);
126 
127 		//! Specifies that future signals of type \c inType should be ignored.
128 		static void setIgnoreAction(SignalType inType);
129 
130 	 protected:
131 		//! Convert native signal number into a portable signal type.
132 		static SignalType convertFromNativeSignal(int inNativeNumber);
133 
134 		//! Convert a portable signal type into a native signal number.
135 		static int convertToNativeSignal(SignalType inType);
136 
137 	 private:
138 		//! Pointer to signal handler function.
139 		typedef void (*HandlerPointer) (int);
140 
141 		//! Action structure (pointer to either internal or external handler).
142 		struct Action {
143 			SignalHandler* mHandler;
144 			HandlerPointer mFunc;
ActionPACC::SignalHandler::Action145 			Action(SignalHandler* inHandler, HandlerPointer inFunc) : mHandler(inHandler), mFunc(inFunc) {}
146 		};
147 
148 		static stack<Action> smActions[NSIGNALS]; //!< Table of signal handler stacks.
149 
150 		//! Run the current custom action for native signal \c inSignal.
151 		static void runAction(int inSignal);
152 	};
153 
154 } // end of PACC namespace
155 
156 #endif
157