From 693a07e52942cad5d9d6e15b7c8a3b1f75a71f6e Mon Sep 17 00:00:00 2001 From: Axel Kittenberger Date: Sat, 12 May 2018 15:08:14 +0200 Subject: [PATCH] reworking signal system --- CMakeLists.txt | 1 + core/mci.c | 12 ++++-- core/signal.c | 25 ++++++++---- default/signal.lua | 62 ++++++++++++++++++++++++++++++ mantle/mci.lua | 9 ++--- mantle/signal.lua | 96 +++++++++++++++++++++++----------------------- mantle/userenv.lua | 2 + 7 files changed, 140 insertions(+), 67 deletions(-) create mode 100644 default/signal.lua diff --git a/CMakeLists.txt b/CMakeLists.txt index 8eabe44..7350002 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,6 +91,7 @@ add_custom_command( OUTPUT signames.lua # set( DEFAULT_CODE ${PROJECT_SOURCE_DIR}/default/default.lua + ${PROJECT_SOURCE_DIR}/default/signal.lua ${PROJECT_SOURCE_DIR}/default/rsync.lua ${PROJECT_SOURCE_DIR}/default/rsyncssh.lua ${PROJECT_SOURCE_DIR}/default/direct.lua diff --git a/core/mci.c b/core/mci.c index 6a8f7d5..0d865b4 100644 --- a/core/mci.c +++ b/core/mci.c @@ -773,8 +773,10 @@ mci_load_default( // loads the default sync implementations if( luaL_loadbuffer( L, default_out, default_size, "default" ) ) { - printlogf( L, "Error", - "loading default sync implementations: %s", lua_tostring( L, -1 ) ); + printlogf( + L, "Error", + "loading default sync implementations: %s", lua_tostring( L, -1 ) + ); exit( -1 ); } @@ -787,8 +789,10 @@ mci_load_default( // prepares the default sync implementations if( lua_pcall( L, 0, 0, 0 ) ) { - printlogf( L, "Error", - "preparing default sync implementations: %s", lua_tostring( L, -1 ) ); + printlogf( + L, "Error", + "preparing default sync implementations: %s", lua_tostring( L, -1 ) + ); exit( -1 ); } diff --git a/core/signal.c b/core/signal.c index 234c274..8cab0cd 100644 --- a/core/signal.c +++ b/core/signal.c @@ -60,16 +60,14 @@ volatile sig_atomic_t sigcode = 0; /* | signal handler */ -/* static void signal_child( int sig ) { // Nothing! // // 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 h; struct sigaction act; + bool have_sig_child = false; // the block mask includes all signals that have registered handlers. // it is used to block all signals outside the select() call @@ -158,7 +157,8 @@ l_onsignal( int signum = lua_tointegerx( L, -1 , &ok ); 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++ ) { if( handlers[ h ] == signum ) @@ -170,7 +170,8 @@ l_onsignal( 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++ ) { int signum = handlers[ h ]; @@ -224,15 +225,23 @@ l_onsignal( int signum = lua_tointegerx( L, -1 , &ok ); if( !ok ) continue; + if( signum == SIGCHLD ) have_sig_child = true; + // stores registered signal handlers handlers[ handlers_len++ ] = signum; sigaction( signum, &act, 0 ); } - // FIXME listen to SIGCHLD if not specified - // Listens to SIGCHLD, but blocks it until pselect( ) - // opens the signal handler up. + // If there is no custom SIGCHLD handler add one + // that will do nothing. This is needed by the OS + // 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; } diff --git a/default/signal.lua b/default/signal.lua new file mode 100644 index 0000000..39c83b4 --- /dev/null +++ b/default/signal.lua @@ -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 +-- +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 diff --git a/mantle/mci.lua b/mantle/mci.lua index 4018ed5..51b081b 100644 --- a/mantle/mci.lua +++ b/mantle/mci.lua @@ -386,7 +386,7 @@ function mci.initialize os.exit( -1 ) end - initSignalHandlers( firstTime ) + if userENV.init then userENV.init( ) end lastReportedWaiting = false @@ -496,7 +496,7 @@ end -- function mci.getAlarm ( ) - log( 'Function', 'getAlarm( )' ) + log( 'Function', 'getAlarm( )', lsyncdStatus ) if lsyncdStatus ~= 'run' then return false end @@ -537,10 +537,7 @@ function mci.getAlarm checkAlarm( s:getAlarm( ) ) end else - log( - 'Alarm', - 'at global process limit.' - ) + log( 'Alarm', 'at global process limit.' ) end -- checks if a statusfile write has been delayed diff --git a/mantle/signal.lua b/mantle/signal.lua index f1486ef..0bdf15b 100644 --- a/mantle/signal.lua +++ b/mantle/signal.lua @@ -38,90 +38,88 @@ local sigHandlerCount = 0 -- --- Prepares an onsignal handle. --- It changes the mantle data, but does not yet tell the core about it. +-- transforms a signal name or number to +-- 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 - handler -- function to call - -- -- or nil to unload the handle - -- -- or false to disable default signal handlers + signal ) - local signum - if type( signal ) == 'number' then if signal < 0 or signal ~= signal or signal - floor( signal ) ~= 0 then - error( 'signal ' .. signal .. ' is an invalid number.' , 2 ) + error( 'signal ' .. signal .. ' is an invalid number.' , 3 ) end - signum = signal + + return signal elseif type( signal ) == 'string' then signum = signums[ signal ] + if signum == nil then - error( 'signal "' .. signal .. '" unknown.' , 2 ) + error( 'signal "' .. signal .. '" unknown.' , 3 ) 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 + -- -- The onsignal( ) function exported to userEnv. -- function onsignal ( - signal, -- signal number or name - handler -- function to call - -- -- or nil to unload the handle - -- -- or false to disable default signal handlers + ... + --- signal1, -- signal number or name + --- handler1 -- function to call + -- -- 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 ) end -- --- Sets up the default HUP/INT/TERM signal handlers. +-- Returns signal handler registered for 'signum' -- --- Called after user scripts finished --- -function initSignalHandlers +function getsignal ( - firstTime --- TODO check if needed + signum ) - onsignalPrep( - '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 ) + return sigHandlers[ signum ]; end diff --git a/mantle/userenv.lua b/mantle/userenv.lua index 016cc5d..58e995e 100644 --- a/mantle/userenv.lua +++ b/mantle/userenv.lua @@ -21,6 +21,7 @@ userENV = dofile = dofile, error = error, getmetatable = getmetable, + getsignal = getsignal, io = io, ipairs = ipairs, load = load, @@ -29,6 +30,7 @@ userENV = math = math, module = module, next = next, + onsignal = onsignal, os = os, package = package, pairs = pairs,