32 void gcleanup_handler(
int signum ) ;
33 using Handler = void (*)(int) ;
47 static void add(
bool (*fn)(
SignalSafe,
const char*) ,
const char * ) ;
50 static void installDefault(
const SignalSafe & ,
int ) ;
53 static void installDefault(
int ) ;
56 static void installIgnore(
int ) ;
59 static void callHandlers() ;
66 static void atexit(
bool active ) ;
69 static void block() noexcept ;
72 static void release() noexcept ;
75 static const char * strdup_ignore_leaks(
const char * p ) ;
89 static void install(
int , Handler ,
bool ) ;
90 static void installHandler(
int ) ;
91 static bool ignored(
int ) ;
92 static void atexitHandler() ;
93 static Link * new_link_ignore_leak() ;
96 static Link * m_head ;
97 static Link * m_tail ;
98 static bool m_atexit_active ;
99 static bool m_atexit_installed ;
100 static std::array<int,4U> m_signals ;
103std::array<int,4U> G::CleanupImp::m_signals = {{ SIGTERM , SIGINT , SIGHUP , SIGQUIT }} ;
104G::CleanupImp::Link * G::CleanupImp::m_head = nullptr ;
105G::CleanupImp::Link * G::CleanupImp::m_tail = nullptr ;
106bool G::CleanupImp::m_atexit_installed = false ;
107bool G::CleanupImp::m_atexit_active = false ;
113 CleanupImp::installIgnore( SIGPIPE ) ;
118 CleanupImp::add( fn , arg ) ;
123 CleanupImp::atexit( active ) ;
128 CleanupImp::block() ;
133 CleanupImp::release() ;
138 return CleanupImp::strdup_ignore_leaks( p ) ;
143 return CleanupImp::strdup_ignore_leaks( s.c_str() ) ;
148void G::CleanupImp::init()
153 installIgnore( SIGPIPE ) ;
154 for(
int s : m_signals )
155 installHandler( s ) ;
158void G::CleanupImp::add(
bool (*fn)(SignalSafe,
const char*) ,
const char * arg )
160 Link * p = new_link_ignore_leak() ;
166 Cleanup::Block block ;
167 if( m_head ==
nullptr ) init() ;
168 if( m_tail !=
nullptr ) m_tail->next = p ;
170 if( m_head ==
nullptr ) m_head = p ;
173G::CleanupImp::Link * G::CleanupImp::new_link_ignore_leak()
178void G::CleanupImp::installHandler(
int signum )
180 if( ignored(signum) )
181 G_DEBUG(
"G::CleanupImp::installHandler: signal " << signum <<
" is ignored" ) ;
183 install( signum , gcleanup_handler ,
true ) ;
186bool G::CleanupImp::ignored(
int signum )
188 struct ::sigaction action {} ;
189 if( ::sigaction( signum ,
nullptr , &action ) != 0 )
190 throw Cleanup::Error(
"sigaction" ) ;
191 return action.sa_handler == SIG_IGN ;
194void G::CleanupImp::installDefault(
int signum )
196 install( signum , SIG_DFL ,
true ) ;
199void G::CleanupImp::installDefault(
const G::SignalSafe & ,
int signum )
201 install( signum , SIG_DFL ,
false ) ;
204void G::CleanupImp::installIgnore(
int signum )
206 install( signum , SIG_IGN ,
true ) ;
209void G::CleanupImp::install(
int signum , Handler fn ,
bool do_throw )
212 struct ::sigaction action {} ;
213 action.sa_handler = fn ;
214 if( ::sigaction( signum , &action ,
nullptr ) != 0 && do_throw )
215 throw Cleanup::Error(
"sigaction" ) ;
218void G::CleanupImp::atexit(
bool active )
220 if( active && !m_atexit_installed )
222 m_atexit_installed = true ;
223 ::atexit( atexitHandler ) ;
225 m_atexit_active = active ;
228void G::CleanupImp::atexitHandler()
230 if( m_atexit_active )
234void G::CleanupImp::callHandlers()
236 if( !callHandlersOnce( SignalSafe() ) )
239 callHandlersOnce( SignalSafe() ) ;
243bool G::CleanupImp::callHandlersOnce( SignalSafe )
246 for( Link * p = m_head ; p != nullptr ; p = p->next )
250 if( !p->done && (*(p->fn))(SignalSafe(),p->arg) )
262extern "C" void gcleanup_handler(
int signum )
267 G::CleanupImp::callHandlers() ;
268 std::_Exit( signum + 128 ) ;
275void G::CleanupImp::block() noexcept
278 sigemptyset( &set ) ;
279 for(
int s : m_signals )
281 sigaddset( &set , s ) ;
283 gdef_pthread_sigmask( SIG_BLOCK , &set ,
nullptr ) ;
286void G::CleanupImp::release() noexcept
289 sigemptyset( &emptyset ) ;
291 sigemptyset( &set ) ;
292 gdef_pthread_sigmask( SIG_BLOCK , &emptyset , &set ) ;
293 for(
int s : m_signals )
295 sigdelset( &set , s ) ;
297 gdef_pthread_sigmask( SIG_SETMASK , &set ,
nullptr ) ;
300const char * G::CleanupImp::strdup_ignore_leaks(
const char * p )
302 return ::strdup( p ) ;
A static implementation class used by G::Cleanup.
static const char * strdup(const char *)
A strdup() function that makes it clear in the stack trace that leaks are expected.
static void atexit(bool active=true)
Ensures that the cleanup functions are also called via atexit(), in addition to abnormal-termination ...
static void release() noexcept
Releases block()ed signals.
static void add(bool(*fn)(SignalSafe, const char *), const char *arg)
Adds the given handler to the list of handlers that are to be called when the process terminates abno...
static void block() noexcept
Temporarily blocks signals until release()d.
static void init()
An optional early-initialisation function. May be called more than once.
static void atExit() noexcept
Re-acquires special privileges just before process exit.
An empty structure that is used to indicate a signal-safe, reentrant implementation.