reworking signal system

This commit is contained in:
Axel Kittenberger 2018-05-12 15:08:14 +02:00
parent a9e609d60c
commit 693a07e529
7 changed files with 140 additions and 67 deletions

View File

@ -91,6 +91,7 @@ add_custom_command( OUTPUT signames.lua
# #
set( DEFAULT_CODE set( DEFAULT_CODE
${PROJECT_SOURCE_DIR}/default/default.lua ${PROJECT_SOURCE_DIR}/default/default.lua
${PROJECT_SOURCE_DIR}/default/signal.lua
${PROJECT_SOURCE_DIR}/default/rsync.lua ${PROJECT_SOURCE_DIR}/default/rsync.lua
${PROJECT_SOURCE_DIR}/default/rsyncssh.lua ${PROJECT_SOURCE_DIR}/default/rsyncssh.lua
${PROJECT_SOURCE_DIR}/default/direct.lua ${PROJECT_SOURCE_DIR}/default/direct.lua

View File

@ -773,8 +773,10 @@ mci_load_default(
// loads the default sync implementations // loads the default sync implementations
if( luaL_loadbuffer( L, default_out, default_size, "default" ) ) if( luaL_loadbuffer( L, default_out, default_size, "default" ) )
{ {
printlogf( L, "Error", printlogf(
"loading default sync implementations: %s", lua_tostring( L, -1 ) ); L, "Error",
"loading default sync implementations: %s", lua_tostring( L, -1 )
);
exit( -1 ); exit( -1 );
} }
@ -787,8 +789,10 @@ mci_load_default(
// prepares the default sync implementations // prepares the default sync implementations
if( lua_pcall( L, 0, 0, 0 ) ) if( lua_pcall( L, 0, 0, 0 ) )
{ {
printlogf( L, "Error", printlogf(
"preparing default sync implementations: %s", lua_tostring( L, -1 ) ); L, "Error",
"preparing default sync implementations: %s", lua_tostring( L, -1 )
);
exit( -1 ); exit( -1 );
} }

View File

@ -60,16 +60,14 @@ volatile sig_atomic_t sigcode = 0;
/* /*
| signal handler | signal handler
*/ */
/*
static void static void
signal_child( int sig ) signal_child( int sig )
{ {
// Nothing! // Nothing!
// //
// This signal handler is just installed so the kernel // This signal handler is just installed so the kernel
// keeps finished child processes as zombies waiting to be reaped. // keeps finished sub-processes as zombies waiting to be reaped.
} }
*/
/* /*
@ -132,6 +130,7 @@ l_onsignal(
int ok; int ok;
int h; int h;
struct sigaction act; struct sigaction act;
bool have_sig_child = false;
// the block mask includes all signals that have registered handlers. // the block mask includes all signals that have registered handlers.
// it is used to block all signals outside the select() call // it is used to block all signals outside the select() call
@ -158,7 +157,8 @@ l_onsignal(
int signum = lua_tointegerx( L, -1 , &ok ); int signum = lua_tointegerx( L, -1 , &ok );
if( !ok ) continue; if( !ok ) continue;
// unsets this signal from the handlers buffer // marks this signal to be used again in the
// new signal handler table.
for( h = 0; h < handlers_len; h++ ) for( h = 0; h < handlers_len; h++ )
{ {
if( handlers[ h ] == signum ) if( handlers[ h ] == signum )
@ -170,7 +170,8 @@ l_onsignal(
sigc++; sigc++;
} }
// resets no longer handlerd signals to default action // resets no longer handled signals
// to their system default action
for( h = 0; h < handlers_len; h++ ) for( h = 0; h < handlers_len; h++ )
{ {
int signum = handlers[ h ]; int signum = handlers[ h ];
@ -224,15 +225,23 @@ l_onsignal(
int signum = lua_tointegerx( L, -1 , &ok ); int signum = lua_tointegerx( L, -1 , &ok );
if( !ok ) continue; if( !ok ) continue;
if( signum == SIGCHLD ) have_sig_child = true;
// stores registered signal handlers // stores registered signal handlers
handlers[ handlers_len++ ] = signum; handlers[ handlers_len++ ] = signum;
sigaction( signum, &act, 0 ); sigaction( signum, &act, 0 );
} }
// FIXME listen to SIGCHLD if not specified // If there is no custom SIGCHLD handler add one
// Listens to SIGCHLD, but blocks it until pselect( ) // that will do nothing. This is needed by the OS
// opens the signal handler up. // so the Lsyncd subprocesses are zombified and
// can be reaped.
if( !have_sig_child )
{
act.sa_handler = &signal_child;
sigaction( SIGCHLD, &act, 0 );
}
return 0; return 0;
} }

62
default/signal.lua Normal file
View File

@ -0,0 +1,62 @@
--
-- signal.lua from Lsyncd -- the Live (Mirror) Syncing Demon
--
--
-- The default signal handles for HUP, INT and TERM.
--
--
-- License: GPLv2 (see COPYING) or any later version
-- Authors: Axel Kittenberger <axkibe@gmail.com>
--
if not default then error( 'default not loaded' ) end
default.signal = { }
local function sighup
( )
print( 'GOT A HUP SIGNAL' )
os.exit( 1 )
end
local function sigint
( )
print( 'GOT AN INT SIGNAL' )
os.exit( 1 )
end
local function sigterm
( )
print( 'GOT A TERM SIGNAL' )
os.exit( 1 )
end
--
-- Sets up the default HUP/INT/TERM signal handlers.
--
-- Called after user scripts finished
--
init =
function
( )
local hup = getsignal( 'HUP' )
local int = getsignal( 'INT' )
local term = getsignal( 'TERM' )
if hup ~= false then hup = sighup end
if int ~= false then int = sigint end
if term ~= false then term = sigterm end
onsignal(
'HUP', hup,
'INT', int,
'TERM', iterm
)
end

View File

@ -386,7 +386,7 @@ function mci.initialize
os.exit( -1 ) os.exit( -1 )
end end
initSignalHandlers( firstTime ) if userENV.init then userENV.init( ) end
lastReportedWaiting = false lastReportedWaiting = false
@ -496,7 +496,7 @@ end
-- --
function mci.getAlarm function mci.getAlarm
( ) ( )
log( 'Function', 'getAlarm( )' ) log( 'Function', 'getAlarm( )', lsyncdStatus )
if lsyncdStatus ~= 'run' then return false end if lsyncdStatus ~= 'run' then return false end
@ -537,10 +537,7 @@ function mci.getAlarm
checkAlarm( s:getAlarm( ) ) checkAlarm( s:getAlarm( ) )
end end
else else
log( log( 'Alarm', 'at global process limit.' )
'Alarm',
'at global process limit.'
)
end end
-- checks if a statusfile write has been delayed -- checks if a statusfile write has been delayed

View File

@ -38,90 +38,88 @@ local sigHandlerCount = 0
-- --
-- Prepares an onsignal handle. -- transforms a signal name or number to
-- It changes the mantle data, but does not yet tell the core about it. -- a valid number. 'false' is left be 'false'
-- --
-- To be used only internally to combine multiple changes into one. -- In case of a invalid signal specifie an error is raised.
-- --
local function onsignalPrep local function toSignum
( (
signal, -- signal number or name signal
handler -- function to call
-- -- or nil to unload the handle
-- -- or false to disable default signal handlers
) )
local signum
if type( signal ) == 'number' if type( signal ) == 'number'
then then
if signal < 0 if signal < 0
or signal ~= signal or signal ~= signal
or signal - floor( signal ) ~= 0 or signal - floor( signal ) ~= 0
then then
error( 'signal ' .. signal .. ' is an invalid number.' , 2 ) error( 'signal ' .. signal .. ' is an invalid number.' , 3 )
end end
signum = signal
return signal
elseif type( signal ) == 'string' elseif type( signal ) == 'string'
then then
signum = signums[ signal ] signum = signums[ signal ]
if signum == nil if signum == nil
then then
error( 'signal "' .. signal .. '" unknown.' , 2 ) error( 'signal "' .. signal .. '" unknown.' , 3 )
end end
else
error( 'signal of type ' .. type( signal ) .. ' invalid.', 2 )
end
sigHandlers[ signum ] = handler return signum
elseif signal == false
then
return false
else
error( 'signal of type ' .. type( signal ) .. ' invalid.', 3 )
end
end end
-- --
-- The onsignal( ) function exported to userEnv. -- The onsignal( ) function exported to userEnv.
-- --
function onsignal function onsignal
( (
signal, -- signal number or name ...
handler -- function to call --- signal1, -- signal number or name
-- -- or nil to unload the handle --- handler1 -- function to call
-- -- or false to disable default signal handlers -- -- or nil to unload the handle
-- -- or false to disable default signal handlers
-- signal2, handler2
-- signal3, handler3
-- and so on
) )
onsignalPrep( signal, handler ) local n = select( '#', ... )
local arg = {...}
if n % 2 ~= 0
then
error( 'onsignal with uneven number of arguments called', 2 )
end
for a = 1, n, 2
do
local signal = arg[ a ]
local handler = arg[ a + 1 ]
local signum = toSignum( signal )
sigHandlers[ signum ] = handler
end
core.onsignal( sigHandlers ) core.onsignal( sigHandlers )
end end
-- --
-- Sets up the default HUP/INT/TERM signal handlers. -- Returns signal handler registered for 'signum'
-- --
-- Called after user scripts finished function getsignal
--
function initSignalHandlers
( (
firstTime --- TODO check if needed signum
) )
onsignalPrep( return sigHandlers[ signum ];
'HUP',
function( )
print( 'GOT A HUP SIGNAL' )
end
)
onsignalPrep(
'INT',
function( )
print( 'GOT A INT SIGNAL' )
end
)
onsignalPrep(
'TERM',
function( )
print( 'GOT A TERM SIGNAL' )
end
)
core.onsignal( sigHandlers )
end end

View File

@ -21,6 +21,7 @@ userENV =
dofile = dofile, dofile = dofile,
error = error, error = error,
getmetatable = getmetable, getmetatable = getmetable,
getsignal = getsignal,
io = io, io = io,
ipairs = ipairs, ipairs = ipairs,
load = load, load = load,
@ -29,6 +30,7 @@ userENV =
math = math, math = math,
module = module, module = module,
next = next, next = next,
onsignal = onsignal,
os = os, os = os,
package = package, package = package,
pairs = pairs, pairs = pairs,