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() ;
63 static bool callHandlersOnce( SignalSafe ) ;
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 ) ;
81 bool (*fn)(SignalSafe,
const char*) ;
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 ) ;
124 CleanupImp::atexit( active ) ;
130 CleanupImp::block() ;
135 CleanupImp::release() ;
141 return CleanupImp::strdup_ignore_leaks( p ) ;
147 return CleanupImp::strdup_ignore_leaks( s.c_str() ) ;
152void G::CleanupImp::init()
157 installIgnore( SIGPIPE ) ;
158 for(
int s : m_signals )
159 installHandler( s ) ;
162void G::CleanupImp::add(
bool (*fn)(SignalSafe,
const char*) ,
const char * arg )
164 Link * p = new_link_ignore_leak() ;
170 Cleanup::Block block ;
171 if( m_head ==
nullptr ) init() ;
172 if( m_tail !=
nullptr ) m_tail->next = p ;
174 if( m_head ==
nullptr ) m_head = p ;
177G::CleanupImp::Link * G::CleanupImp::new_link_ignore_leak()
182void G::CleanupImp::installHandler(
int signum )
184 if( ignored(signum) )
185 G_DEBUG(
"G::CleanupImp::installHandler: signal " << signum <<
" is ignored" ) ;
187 install( signum , gcleanup_handler ,
true ) ;
190bool G::CleanupImp::ignored(
int signum )
192 struct ::sigaction action {} ;
193 if( ::sigaction( signum ,
nullptr , &action ) != 0 )
194 throw Cleanup::Error(
"sigaction" ) ;
195 return action.sa_handler == SIG_IGN ;
199void G::CleanupImp::installDefault(
int signum )
201 install( signum , SIG_DFL ,
true ) ;
206void G::CleanupImp::installDefault(
const G::SignalSafe & ,
int signum )
208 install( signum , SIG_DFL ,
false ) ;
212void G::CleanupImp::installIgnore(
int signum )
214 install( signum , SIG_IGN ,
true ) ;
217void G::CleanupImp::install(
int signum , Handler fn ,
bool do_throw )
220 struct ::sigaction action {} ;
221 action.sa_handler = fn ;
222 if( ::sigaction( signum , &action ,
nullptr ) != 0 && do_throw )
223 throw Cleanup::Error(
"sigaction" ) ;
226void G::CleanupImp::atexit(
bool active )
228 if( active && !m_atexit_installed )
230 m_atexit_installed = true ;
231 ::atexit( atexitHandler ) ;
233 m_atexit_active = active ;
236void G::CleanupImp::atexitHandler()
238 if( m_atexit_active )
242void G::CleanupImp::callHandlers()
244 if( !callHandlersOnce( SignalSafe() ) )
247 callHandlersOnce( SignalSafe() ) ;
251bool G::CleanupImp::callHandlersOnce( SignalSafe )
254 for( Link * p = m_head ; p != nullptr ; p = p->next )
258 if( !p->done && (*(p->fn))(SignalSafe(),p->arg) )
270extern "C" void gcleanup_handler(
int signum )
275 G::CleanupImp::callHandlers() ;
276 std::_Exit( signum + 128 ) ;
283void G::CleanupImp::block() noexcept
286 sigemptyset( &set ) ;
287 for(
int s : m_signals )
289 sigaddset( &set , s ) ;
291 gdef_pthread_sigmask( SIG_BLOCK , &set ,
nullptr ) ;
294void G::CleanupImp::release() noexcept
297 sigemptyset( &emptyset ) ;
299 sigemptyset( &set ) ;
300 gdef_pthread_sigmask( SIG_BLOCK , &emptyset , &set ) ;
301 for(
int s : m_signals )
303 sigdelset( &set , s ) ;
305 gdef_pthread_sigmask( SIG_SETMASK , &set ,
nullptr ) ;
308const char * G::CleanupImp::strdup_ignore_leaks(
const char * p )
310 return ::strdup( p ) ;
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.