35 void gcleanup_handler(
int signum ) ;
36 using Handler = void (*)(int) ;
44 using Arg = Cleanup::Arg ;
53 static void add( Cleanup::Fn , Arg ) ;
54 static void installDefault(
const SignalSafe & ,
int ) noexcept ;
55 static void installDefault(
int ) ;
56 static void installIgnore(
int ) ;
57 static void callHandlers() noexcept ;
58 static
bool callHandlersOnce( SignalSafe ) noexcept ;
59 static
void atexit(
bool active ) ;
60 static
void block() noexcept ;
61 static
void release() noexcept ;
63 static
void install(
int , Handler ) ;
64 static
void install(
int , Handler ,
std::nothrow_t ) noexcept ;
65 static
void installHandler(
int ) ;
66 static
bool ignored(
int ) ;
67 static
void atexitHandler() noexcept ;
68 static Arg duplicate( const
char * ,
std::
size_t ,
bool = false ) ;
69 static Link * new_link_ignore_leak() ;
70 static
char * new_arg_ignore_leak(
std::
size_t ) ;
73 static Link * m_head ;
74 static Link * m_tail ;
75 static
bool m_atexit_active ;
76 static
bool m_atexit_installed ;
77 static
std::array<
int,4U> m_signals ;
81G::CleanupImp::Link *
G::CleanupImp::m_head =
nullptr ;
82G::CleanupImp::Link *
G::CleanupImp::m_tail =
nullptr ;
83bool G::CleanupImp::m_atexit_active = false ;
84bool G::CleanupImp::m_atexit_installed = false ;
85std::array<
int,4U>
G::CleanupImp::m_signals = {{ SIGTERM , SIGINT , SIGHUP , SIGQUIT }} ;
91 CleanupImp::installIgnore( SIGPIPE ) ;
96 CleanupImp::add( fn , arg ) ;
102 CleanupImp::atexit( active ) ;
108 CleanupImp::block() ;
113 CleanupImp::release() ;
119 return CleanupImp::duplicate( p?p:
"" , p?std::strlen(p):0U ) ;
126 return CleanupImp::duplicate( s.data() , s.size() ) ;
132 std::string s = p.
str() ;
133 return CleanupImp::duplicate( s.data() , s.size() ,
true ) ;
139 return CleanupImp::duplicate(
nullptr , 0U ) ;
146bool G::Cleanup::Arg::isPath() const noexcept
152const char * G::Cleanup::Arg::str() const noexcept
159void G::CleanupImp::init()
164 installIgnore( SIGPIPE ) ;
165 for(
int s : m_signals )
166 installHandler( s ) ;
169void G::CleanupImp::add( Cleanup::Fn fn , Arg arg )
173 Link * p = new_link_ignore_leak() ;
179 Cleanup::Block block ;
180 if( m_head ==
nullptr ) init() ;
181 if( m_tail !=
nullptr ) m_tail->next = p ;
183 if( m_head ==
nullptr ) m_head = p ;
186G::CleanupImp::Link * G::CleanupImp::new_link_ignore_leak()
191char * G::CleanupImp::new_arg_ignore_leak( std::size_t n )
193 return static_cast<char*
>(
operator new(n) ) ;
196G::Cleanup::Arg G::CleanupImp::duplicate(
const char * p , std::size_t n ,
bool is_path )
198 G_ASSERT( (n+std::size_t(1U)) > n ) ;
199 if( (n+std::size_t(1U)) <= n )
200 throw Cleanup::Error(
"numeric overflow" ) ;
202 char * pp = new_arg_ignore_leak( n+1U ) ;
203 if( p && n ) std::memcpy( pp , p , n ) ;
208 a.m_is_path = is_path ;
212void G::CleanupImp::installHandler(
int signum )
214 if( ignored(signum) )
215 G_DEBUG(
"G::CleanupImp::installHandler: signal " << signum <<
" is ignored" ) ;
217 install( signum , gcleanup_handler ) ;
220bool G::CleanupImp::ignored(
int signum )
222 struct ::sigaction action {} ;
223 if( ::sigaction( signum ,
nullptr , &action ) != 0 )
224 throw Cleanup::Error(
"sigaction" ) ;
225 return action.sa_handler == SIG_IGN ;
229void G::CleanupImp::installDefault(
int signum )
231 install( signum , SIG_DFL ) ;
236void G::CleanupImp::installDefault(
const G::SignalSafe & ,
int signum )
noexcept
238 install( signum , SIG_DFL , std::nothrow ) ;
242void G::CleanupImp::installIgnore(
int signum )
244 install( signum , SIG_IGN ) ;
247void G::CleanupImp::install(
int signum , Handler fn )
250 struct ::sigaction action {} ;
251 action.sa_handler = fn ;
252 if( ::sigaction( signum , &action ,
nullptr ) != 0 )
253 throw Cleanup::Error(
"sigaction" ) ;
256void G::CleanupImp::install(
int signum , Handler fn , std::nothrow_t )
noexcept
258 struct ::sigaction action {} ;
259 action.sa_handler = fn ;
260 ::sigaction( signum , &action ,
nullptr ) ;
263void G::CleanupImp::atexit(
bool active )
265 if( active && !m_atexit_installed )
267 m_atexit_installed = true ;
268 ::atexit( atexitHandler ) ;
270 m_atexit_active = active ;
273void G::CleanupImp::atexitHandler() noexcept
275 if( m_atexit_active )
279void G::CleanupImp::callHandlers() noexcept
281 if( !callHandlersOnce( SignalSafe() ) )
284 callHandlersOnce( SignalSafe() ) ;
288bool G::CleanupImp::callHandlersOnce( SignalSafe )
noexcept
291 for( Link * p = m_head ; p != nullptr ; p = p->next )
295 if( !p->done && (*(p->fn))(p->arg) )
307extern "C" void gcleanup_handler(
int signum )
310 static_assert(
noexcept(G::CleanupImp::callHandlers()) ,
"" ) ;
311 G::CleanupImp::callHandlers() ;
312 std::_Exit( signum + 128 ) ;
315void G::CleanupImp::block() noexcept
318 sigemptyset( &set ) ;
319 for(
int s : m_signals )
321 sigaddset( &set , s ) ;
323 gdef_pthread_sigmask( SIG_BLOCK , &set ,
nullptr ) ;
326void G::CleanupImp::release() noexcept
329 sigemptyset( &emptyset ) ;
331 sigemptyset( &set ) ;
332 gdef_pthread_sigmask( SIG_BLOCK , &emptyset , &set ) ;
333 for(
int s : m_signals )
335 sigdelset( &set , s ) ;
337 gdef_pthread_sigmask( SIG_SETMASK , &set ,
nullptr ) ;
static Arg arg(const char *)
Duplicates a c-string for add().
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 block() noexcept
Temporarily blocks signals until release()d.
static void init()
An optional early-initialisation function. May be called more than once.
static void add(Fn, Arg arg)
Adds the given handler to the list of handlers that are to be called when the process terminates abno...
A Path object represents a file system path.
std::string str() const
Returns the path string.
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.
Opaque leaky string pointer wrapper created by G::Cleanup::arg().