reworking signal system

This commit is contained in:
Axel Kittenberger 2018-06-04 08:54:06 +02:00
parent 5965c0ea59
commit 9fa9ea72da
18 changed files with 173 additions and 177 deletions

View File

@ -221,7 +221,8 @@ handle_event(
lua_pop( L, 1 );
hup = 1;
// FIXME report this to mantle more sensible
softreset = true;
return;
}
@ -446,7 +447,7 @@ inotify_ready(
{
int i = 0;
while( i < len && !hup && !term )
while( i < len && !softreset )
{
struct inotify_event *event = ( struct inotify_event * ) ( readbuf + i );

View File

@ -208,27 +208,6 @@ masterloop(
lua_pop( L, 1 );
}
// reacts on HUP signals
if( hup )
{
load_mci( L, "hup" );
if( lua_pcall( L, 0, 0, -2 ) ) exit( -1 );
lua_pop( L, 1 );
hup = 0;
}
// reacts on TERM and INT signals
if( term == 1 )
{
load_mci( L, "term" );
lua_pushnumber( L, sigcode );
if( lua_pcall( L, 1, 0, -3 ) ) exit( -1 );
lua_pop( L, 1 );
term = 2;
}
// lets the mantle do stuff every cycle,
// like starting new processes, writing the statusfile etc.
load_mci( L, "cycle" );
@ -500,13 +479,8 @@ main( int argc, char * argv[ ] )
setlinebuf( stdout );
setlinebuf( stderr );
while( !term )
{
main1( argc, argv );
}
while( true ) main1( argc, argv );
// exits with error code responding to the signal it died for
// FIXME this no longer holds true to systemd recommendations
return 128 + sigcode;
// return -1;
}

View File

@ -410,6 +410,18 @@ l_realdir( lua_State *L )
}
/*
| Soft resets Lsyncd.
| Typical as reaction on a HUP signal.
*/
static int
l_softreset( lua_State *L )
{
softreset = 1;
return 0;
}
/*
| Dumps the Lua stack.
| For debugging purposes.
@ -490,7 +502,7 @@ l_readdir( lua_State *L )
lua_newtable( L );
while( !hup && !term )
while( !softreset )
{
struct dirent *de = readdir( d );
bool isdir;
@ -657,6 +669,7 @@ static const luaL_Reg corelib[ ] =
{ "onsignal", l_onsignal },
{ "readdir", l_readdir },
{ "realdir", l_realdir },
{ "sofotreset", l_softreset },
{ "stackdump", l_stackdump },
{ "terminate", l_terminate },
{ NULL, NULL }

View File

@ -24,11 +24,19 @@
#include "mem.h"
/**
| Set to true to soft reset at earliest possilibity.
*/
bool softreset = false;
/**
* An observance to be called when a file descritor becomes
* read-ready or write-ready.
*/
struct observance {
struct observance
{
// The file descriptor to observe.
int fd;
@ -261,14 +269,12 @@ observe_select
struct observance *obs = observances + pi;
int fd = obs->fd;
// checks for signals
if( hup || term ) break;
if( softreset ) break;
// a file descriptor became read-ready
if( obs->ready && FD_ISSET( fd, &rfds ) ) obs->ready( L, fd, obs->extra );
// Checks for signals, again, better safe than sorry
if ( hup || term ) break;
if( softreset ) break;
// FIXME breaks on multiple nonobservances in one beat
if(

View File

@ -33,4 +33,7 @@ extern void observe_tidy_all( );
// stops the core to observe a file descriptor
extern void nonobserve_fd( int fd );
// set to true to soft reset at earliest possilibity
extern bool softreset;
#endif

View File

@ -46,17 +46,6 @@ static int handlers_maxlen;
static int handlers_len;
/*
| Set by TERM or HUP signal handler
| telling Lsyncd should end or reset ASAP.
|
| FIXME remove
*/
volatile sig_atomic_t hup = 0;
volatile sig_atomic_t term = 0;
volatile sig_atomic_t sigcode = 0;
/*
| signal handler
*/
@ -247,11 +236,27 @@ l_onsignal(
}
/*
| Sends a signal to another process.
|
| Params on Lua stack:
| 1: process id (pid) to send a signal to
| 2: the signal to send
|
| Returns on Lua stack:
|
| nada
*/
int
l_kill(
lua_State *L
)
{
int pid = luaL_checkinteger( L, 1 );
int sid = luaL_checkinteger( L, 2 );
kill( pid, sid );
return 0;
}

View File

@ -9,11 +9,6 @@
#ifndef LSYNCD_SIGNAL_H
#define LSYNCD_SIGNAL_H
// set to 1 on hup signal or term signal
extern volatile sig_atomic_t hup;
extern volatile sig_atomic_t term;
extern volatile sig_atomic_t sigcode;
// initializes signal handling.
extern void signal_init( );

View File

@ -98,6 +98,12 @@ default.collect = function
local rc
if agent.syncStopped
then
log( 'Normal', 'Sync stopped, ignoring exitcode of finished child' )
return 'ok'
end
if config.exitcodes
then
rc = config.exitcodes[ exitcode ]
@ -115,9 +121,7 @@ default.collect = function
then
log(
'Normal',
'Startup of ',
agent.source, ' -> ', agent.target,
' finished.'
'Startup of ',agent.source, ' -> ',agent.target,' finished.'
)
return 'ok'
@ -133,15 +137,6 @@ default.collect = function
)
return 'again'
else
log(
'Error',
'Temporary or permanent failure on startup of ',
agent.source, ' -> ', agent.target,
'. Terminating since "insist" is not set.'
)
terminate( -1 )
end
elseif rc == 'die'
then

View File

@ -141,14 +141,7 @@ direct.collect = function
log( 'Normal', 'Startup of "',agent.source,'" finished: ', exitcode )
elseif rc == 'again'
then
if settings( 'insist' )
then
log( 'Normal', 'Retrying startup of "',agent.source,'": ', exitcode )
else
log('Error', 'Temporary or permanent failure on startup of "',
agent.source, '". Terminating since "insist" is not set.');
terminate( -1 )
end
log( 'Normal', 'Retrying startup of "',agent.source,'": ', exitcode )
elseif rc == 'die'
then
log( 'Error', 'Failure on startup of "',agent.source,'": ', exitcode )

View File

@ -365,18 +365,7 @@ rsyncssh.collect = function
log( 'Normal', 'Startup of "', agent.source, '" finished: ', exitcode )
elseif rc == 'again'
then
if settings('insist')
then
log( 'Normal', 'Retrying startup of "', agent.source, '": ', exitcode )
else
log(
'Error',
'Temporary or permanent failure on startup of "',
agent.source, '". Terminating since "insist" is not set.'
)
terminate( -1 ) -- ERRNO
end
log( 'Normal', 'Retrying startup of "', agent.source, '": ', exitcode )
elseif rc == 'die'
then
log( 'Error', 'Failure on startup of "', agent.source, '": ', exitcode )

View File

@ -15,60 +15,64 @@ default.signal = { }
--
-- Returns a signal handler for 'signal'.
--
--
local function onCollect
local function makeSignalHandler
(
sync -- the user intf to the sync a child finished for
sig, -- the signal to handle
logtext, -- text to log
finish -- function to call after all child processes have been collected
)
if( sync.processCount( ) == 0 ) then syncs.remove( sync ) end
return function( )
log( 'Normal', 'Received an ',sig,' signal, ',logtext )
if #syncs == 0 then os.exit( 0 ) end
end
local pCount = 0
for _, sync in ipairs( syncs )
do
sync.stop( )
local function sighup
( )
print( 'GOT A HUP SIGNAL' )
local pids = sync.pids( )
local pc = #pids
os.exit( 1 )
end
if( pc == 0 )
then
syncs.remove( sync )
else
pCount = pCount + pc
sync.onCollect(
function
(
sync -- the user intf to the sync a child finished for
)
if( sync.processCount( ) == 0 ) then syncs.remove( sync ) end
if #syncs == 0 then finish( ) end
end
)
local function sigint
( )
log( 'Normal', 'Received an INT signal, terminating' )
local pCount = 0
for _, sync in ipairs( syncs )
do
sync.stop( )
local c = sync.processCount( )
if( c == 0 )
then
syncs.remove( sync )
else
pCount = pCount + c
sync.onCollect( onCollect )
for _, pid in ipairs( pids ) do signal( pid, sig ) end
end
end
if #syncs == 0 then finish( ) end
log( 'Normal', 'Waiting for ', pCount, ' child processes.' )
end
if #syncs == 0 then os.exit( 0 ) end
log( 'Normal', 'Waiting for ', pCount, ' child processes.' )
end
local function sigterm
( )
print( 'GOT A TERM SIGNAL' )
os.exit( 1 )
local function finishHup( )
os.exit( 0 )
end
local function finishInt( )
os.exit( 0 )
end
local function finishTerm( )
os.exit( 0 )
end
--
-- Sets up the default HUP/INT/TERM signal handlers.
@ -82,14 +86,10 @@ init =
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
if hup ~= false then hup = makeSignalHandler( 'HUP', 'resetting', finishHup ) end
if int ~= false then int = makeSignalHandler( 'INT', 'terminating', finishInt ) end
if term ~= false then term = makeSignalHandler( 'TERM', 'terminating', finishTerm ) end
onsignal(
'HUP', hup,
'INT', int,
'TERM', term
)
onsignal( 'HUP', hup, 'INT', int, 'TERM', term )
end

View File

@ -54,9 +54,6 @@ OPTIONS
*-help*::
Show a help message.
*-insist*::
Continues start up even if rsync cannot connect.
*-log* 'LEVEL'::
Controls which kind of events are logged. By default Lsyncd logs 'Normal'
and 'Error' Messages. *-log scarce* will make Lsyncd log Error messages

View File

@ -95,24 +95,6 @@ mt.__ipairs = function
end
--
-- Creates a new counter.
--
local function new
( )
-- k_nt is a native table, private to this object.
local o =
{
[ k_size ] = 0,
[ k_nt ] = { }
}
setmetatable( o, mt )
return o
end
--
-- Creates a copy of the counter
--
@ -132,8 +114,27 @@ local function copy
return copy
end
--
-- Creates a new counter.
--
local function new
( )
-- k_nt is a native table, private to this object.
local o =
{
[ k_size ] = 0,
[ k_nt ] = { }
}
setmetatable( o, mt )
return o
end
--
-- Exported interface.
--
Counter = { new = new }
Counter = { new = new, copy = copy }

View File

@ -268,6 +268,17 @@ local eventFields =
return e2d[ event ].sync.source .. cutSlash( getPath( event ) )
end,
--
-- Returns true if the sync this event belongs
-- to is stopped
--
syncStopped = function
(
event
)
return e2d[ event ].sync.stopped
end,
--
-- Returns the configured target.
--
@ -411,15 +422,9 @@ local eventListMeta =
elist,
func
)
if func == 'isList'
then
return true
end
if func == 'isList' then return true end
if func == 'config'
then
return e2d[ elist ].sync.config
end
if func == 'config' then return e2d[ elist ].sync.config end
local f = eventListFuncs[ func ]

View File

@ -563,6 +563,7 @@ end
--
mci.inotifyEvent = Inotify.event
--
-- Collector for every child process that finished in startup phase
--
@ -593,6 +594,7 @@ end
--
-- Called by core on a hup signal.
-- FIXME remove
--
function mci.hup
( )
@ -601,8 +603,10 @@ function mci.hup
lsyncdStatus = 'fade'
end
--
-- Called by core on a term signal.
-- FIXME remove
--
function mci.term
(

View File

@ -43,7 +43,7 @@ local sigHandlerCount = 0
--
-- In case of a invalid signal specifie an error is raised.
--
local function toSignum
function signum
(
signal
)
@ -59,14 +59,9 @@ local function toSignum
return signal
elseif type( signal ) == 'string'
then
signum = signums[ signal ]
if signum == nil
then
error( 'signal "' .. signal .. '" unknown.' , 3 )
end
return signum
local sn = signums[ signal ]
if sn == nil then error( 'signal "' .. signal .. '" unknown.' , 3 ) end
return sn
elseif signal == false
then
return false
@ -102,10 +97,8 @@ function onsignal
do
local signal = arg[ a ]
local handler = arg[ a + 1 ]
local signum = toSignum( signal )
sigHandlers[ signum ] = handler
local sn = signum( signal )
sigHandlers[ sn ] = handler
end
core.onsignal( sigHandlers )
@ -131,16 +124,29 @@ mci.signalEvent =
(
sigtable
)
for _, signum in ipairs( sigtable )
for _, sn in ipairs( sigtable )
do
local handler = sigHandlers[ signum ]
local handler = sigHandlers[ sn ]
if not handler
then
log( 'Error', 'Received signal '..signnum..' without a handler.' )
log( 'Error', 'Received signal ',sn,' without a handler.' )
end
handler( )
end
end
--
-- Sends a signal to another process.
--
function signal
(
pid, -- process to send the signal to
signal -- the signal to send
)
core.kill( pid, signum( signal ) )
end

View File

@ -766,7 +766,14 @@ local function getUserIntf
-- processes
pids = function
( )
return self.processes:copy( )
local c = 1
local pids = { }
for pid, delay in pairs( self.processes )
do
pids[ c ] = pid
c = c + 1
end
return pids
end,
processCount = function

View File

@ -43,6 +43,7 @@ userenv =
require = require,
select = select,
setmetatable = setmetatable,
signum = signum,
string = string,
table = table,
type = type,
@ -57,6 +58,7 @@ userenv =
nonobservefs = user.nonobserfd,
observefd = user.observefd,
settings = user.settings,
signal = signal,
spawn = user.spawn,
spawnShell = user.spawnShell,
sync = user.sync,