- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gcleanup_unix.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2013 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gcleanup_unix.cpp
19 //
20
21 #include "gdef.h"
22 #include "gcleanup.h"
23 #include "gprocess.h"
24 #include "groot.h"
25 #include "glog.h"
26 #include <signal.h>
27
28 extern "C"
29 {
30 void gcleanup_unix_handler_( int signum ) ;
31 typedef void (*Handler)( int ) ;
32 }
33
34 namespace G
35 {
36 class CleanupImp ;
37 }
38
42 class G::CleanupImp
43 {
44 public:
45 static void add( void (*fn)(SignalSafe,const char*) , const char * ) ;
46 static void installDefault( int ) ;
47 static void callHandlers() ;
48 static void ignore( int ) ;
49
50 private:
51 static void init() ;
52 static void install( int , Handler ) ;
53 static void installHandler( int ) ;
54 static bool ignored( int ) ;
55
56 private:
58 struct Link
59 {
60 void (*fn)(SignalSafe,const char*) ;
61 const char * arg ;
62 Link * next ;
63 } ;
64 static Link * m_head ;
65 static Link * m_tail ;
66 } ;
67
68 G::CleanupImp::Link * G::CleanupImp::m_head = NULL ;
69 G::CleanupImp::Link * G::CleanupImp::m_tail = NULL ;
70
71 // ===
72
73 void G::Cleanup::init()
74 {
75 CleanupImp::ignore( SIGPIPE ) ;
76 }
77
78 void G::Cleanup::add( void (*fn)(SignalSafe,const char*) , const char * arg )
79 {
80 if( arg != NULL )
81 CleanupImp::add( fn , arg ) ;
82 }
83
84 // ===
85
86 void G::CleanupImp::init()
87 {
88 // install our meta-handler for signals that normally terminate the process,
89 // except for sigpipe which we ignore
90 //
91 ignore( SIGPIPE ) ;
92 installHandler( SIGTERM ) ;
93 installHandler( SIGINT ) ;
94 installHandler( SIGHUP ) ;
95 installHandler( SIGQUIT ) ;
96 //installHandler( SIGUSR1 ) ;
97 //installHandler( SIGUSR2 ) ;
98 }
99
100 void G::CleanupImp::add( void (*fn)(SignalSafe,const char*) , const char * arg )
101 {
102 Link * p = new Link ;
103 p->fn = fn ;
104 p->arg = arg ;
105 p->next = NULL ;
106
107 // (this bit should be protected from signals)
108 if( m_head == NULL ) init() ;
109 if( m_tail != NULL ) m_tail->next = p ;
110 m_tail = p ;
111 if( m_head == NULL ) m_head = p ;
112 }
113
114 void G::CleanupImp::installHandler( int signum )
115 {
116 if( ignored(signum) )
117 G_DEBUG( "G::CleanupImp::installHandler: signal " << signum << " is ignored" ) ;
118 else
119 install( signum , gcleanup_unix_handler_ ) ;
120 }
121
122 void G::CleanupImp::installDefault( int signum )
123 {
124 install( signum , NULL ) ;
125 }
126
127 bool G::CleanupImp::ignored( int signum )
128 {
129 static struct sigaction zero_action ;
130 struct sigaction action( zero_action ) ;
131 if( ::sigaction( signum , NULL , &action ) )
132 throw Cleanup::Error( "sigaction" ) ;
133 return action.sa_handler == SIG_IGN ;
134 }
135
136 void G::CleanupImp::install( int signum , Handler fn )
137 {
138 // install the given handler, or the system default if null
139 static struct sigaction zero_action ;
140 struct sigaction action( zero_action ) ;
141 action.sa_handler = fn ? fn : SIG_DFL ;
142 if( ::sigaction( signum , &action , NULL ) && fn != NULL )
143 throw Cleanup::Error( "sigaction" ) ;
144 }
145
146 void G::CleanupImp::ignore( int signum )
147 {
148 static struct sigaction zero_action ;
149 struct sigaction action( zero_action ) ;
150 action.sa_handler = SIG_IGN ;
151 if( ::sigaction( signum , &action , NULL ) )
152 throw Cleanup::Error( "sigaction" ) ;
153 }
154
155 void G::CleanupImp::callHandlers()
156 {
157 G::Root claim_root ;
158 for( const Link * p = m_head ; p != NULL ; p = p->next )
159 {
160 (*(p->fn))(SignalSafe(),p->arg) ;
161 }
162 }
163
164 extern "C"
165 void gcleanup_unix_handler_( int signum )
166 {
167 // call the registered handler(s) and then do the system default action
168 try
169 {
170 int e = G::Process::errno_() ;
171 G::CleanupImp::callHandlers() ;
172 G::CleanupImp::installDefault( signum ) ;
173 G::Process::errno_( e ) ;
174 ::raise( signum ) ;
175 }
176 catch(...)
177 {
178 }
179 }
180
G::SignalSafe
An empty structure that is used to indicate a signal-safe, reentrant implementation.
Definition: gsignalsafe.h:35
glog.h
G::CleanupImp::add
static void add(void(*fn)(SignalSafe, const char *), const char *)
Definition: gcleanup_unix.cpp:100
G::Root
A class which acquires the process's special privileges on construction and releases them on destruct...
Definition: groot.h:49
groot.h
gcleanup_unix_handler_
void gcleanup_unix_handler_(int signum)
Definition: gcleanup_unix.cpp:165
gcleanup.h
G::CleanupImp::ignore
static void ignore(int)
Definition: gcleanup_unix.cpp:146
G::Process::errno_
static int errno_()
Returns the process's current 'errno' value.
Definition: gprocess_unix.cpp:107
G
Low-level classes.
gprocess.h
G_DEBUG
#define G_DEBUG(expr)
Definition: glog.h:95
G::Cleanup::init
static void init()
An optional early-initialisation function.
Definition: gcleanup_unix.cpp:73
G::CleanupImp::callHandlers
static void callHandlers()
Definition: gcleanup_unix.cpp:155
G::CleanupImp
A private implementation class used by G::Cleanup.
Definition: gcleanup_unix.cpp:42
G::CleanupImp::installDefault
static void installDefault(int)
Definition: gcleanup_unix.cpp:122
Handler
void(* Handler)(int)
Definition: gcleanup_unix.cpp:31
G::Cleanup::add
static void add(void(*fn)(SignalSafe, const char *), const char *arg)
Adds the given handler to the list which are to be called when the process terminates abnormally...
Definition: gcleanup_unix.cpp:78