reworking signal system

This commit is contained in:
Axel Kittenberger 2018-05-06 22:46:00 +02:00
parent 0425ff230c
commit 8a5da303c6
8 changed files with 152 additions and 71 deletions

View File

@ -65,10 +65,10 @@ set( MANTLE_CODE
${PROJECT_SOURCE_DIR}/mantle/syncmaster.lua ${PROJECT_SOURCE_DIR}/mantle/syncmaster.lua
${PROJECT_SOURCE_DIR}/mantle/monitor.lua ${PROJECT_SOURCE_DIR}/mantle/monitor.lua
${PROJECT_SOURCE_DIR}/mantle/fwriter.lua ${PROJECT_SOURCE_DIR}/mantle/fwriter.lua
${PROJECT_SOURCE_DIR}/mantle/signal.lua
${PROJECT_SOURCE_DIR}/mantle/statusfile.lua ${PROJECT_SOURCE_DIR}/mantle/statusfile.lua
${PROJECT_SOURCE_DIR}/mantle/useralarm.lua ${PROJECT_SOURCE_DIR}/mantle/useralarm.lua
${PROJECT_SOURCE_DIR}/mantle/mci.lua ${PROJECT_SOURCE_DIR}/mantle/mci.lua
${PROJECT_SOURCE_DIR}/mantle/signal.lua
${PROJECT_SOURCE_DIR}/mantle/user.lua ${PROJECT_SOURCE_DIR}/mantle/user.lua
${PROJECT_SOURCE_DIR}/mantle/string.lua ${PROJECT_SOURCE_DIR}/mantle/string.lua
${PROJECT_SOURCE_DIR}/mantle/version.lua ${PROJECT_SOURCE_DIR}/mantle/version.lua

View File

@ -460,6 +460,7 @@ l_stackdump( lua_State * L )
return 0; return 0;
} }
/* /*
| Reads the directories entries. | Reads the directories entries.
| |
@ -650,7 +651,7 @@ static const luaL_Reg corelib[ ] =
{ "now", l_now }, { "now", l_now },
{ "nonobserve_fd", l_nonobserve_fd }, { "nonobserve_fd", l_nonobserve_fd },
{ "observe_fd", l_observe_fd }, { "observe_fd", l_observe_fd },
// { "onsignal", l_onsignal }, { "onsignal", l_onsignal },
{ "readdir", l_readdir }, { "readdir", l_readdir },
{ "realdir", l_realdir }, { "realdir", l_realdir },
{ "stackdump", l_stackdump }, { "stackdump", l_stackdump },

View File

@ -27,7 +27,7 @@
#include "log.h" #include "log.h"
/* /*
| "Secured" calloc | "Secured" calloc.
*/ */
extern void * extern void *
s_calloc( size_t nmemb, size_t size ) s_calloc( size_t nmemb, size_t size )
@ -63,7 +63,7 @@ s_malloc( size_t size )
/* /*
| "Secured" realloc | "Secured" realloc.
*/ */
extern void * extern void *
s_realloc( void * ptr, size_t size ) s_realloc( void * ptr, size_t size )
@ -81,7 +81,7 @@ s_realloc( void * ptr, size_t size )
/* /*
| "Secured" strdup | "Secured" strdup.
*/ */
extern char * extern char *
s_strdup( const char *src ) s_strdup( const char *src )

View File

@ -240,11 +240,12 @@ observe_select
// that puts Lsyncd to sleep until anything worth noticing // that puts Lsyncd to sleep until anything worth noticing
// happens // happens
pr = pselect( pr =
observances[ observances_len - 1 ].fd + 1, pselect(
&rfds, &wfds, NULL, observances[ observances_len - 1 ].fd + 1,
timeout, &sigset &rfds, &wfds, NULL,
); timeout, &sigset
);
// FIXME handle signals // FIXME handle signals

View File

@ -10,7 +10,9 @@
*/ */
#include "feature.h" #include "feature.h"
#include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h>
#include <signal.h> #include <signal.h>
#include <string.h> #include <string.h>
@ -19,6 +21,7 @@
#include <lualib.h> #include <lualib.h>
#include <lauxlib.h> #include <lauxlib.h>
#include "log.h"
#include "mem.h" #include "mem.h"
@ -26,13 +29,6 @@ static volatile sig_atomic_t * queue;
static int queue_len; static int queue_len;
static int queue_pos; static int queue_pos;
/*
| XXX
*/
static int *handlers;
static int handlers_len;
static int handlers_maxlen;
/* /*
| Set by TERM or HUP signal handler | Set by TERM or HUP signal handler
@ -49,7 +45,8 @@ volatile sig_atomic_t sigcode = 0;
/* /*
| signal handler | signal handler
*/ */
static void signal_child( int sig ) static void
signal_child( int sig )
{ {
// Nothing! // Nothing!
// //
@ -64,23 +61,24 @@ static void signal_child( int sig )
static void static void
signal_handler( int sig ) signal_handler( int sig )
{ {
switch( sig ) // looks if this signal is already queued
for( int i = 0; i < queue_pos; i++ )
{ {
case SIGTERM: // if so it is dropped
case SIGINT: if( queue[ i ] == sig ) return;
term = 1;
sigcode = sig;
return;
case SIGHUP:
hup = 1;
return;
} }
if( queue_pos + 1 >= queue_len )
{
// this should never ever happen
logstring( "Error", "Signal queue overflow!" );
exit( -1 );
}
queue[ queue_pos++ ] = sig;
} }
/* /*
| Initializes signal handling. | Initializes signal handling.
| |
@ -93,22 +91,90 @@ signal_init( )
queue_len = 5; queue_len = 5;
queue = s_malloc( queue_len * sizeof( sig_atomic_t ) ); queue = s_malloc( queue_len * sizeof( sig_atomic_t ) );
queue_pos = 0; queue_pos = 0;
handlers_maxlen = 5;
handlers_len = 0;
handlers = s_malloc( handlers_maxlen * sizeof( int * ) );
} }
/* /*
sigset_t set; | Registers (or deregisters) a signal handlers.
sigemptyset( &set ); |
sigaddset( &set, SIGCHLD ); | Params on Lua stack:
signal( SIGCHLD, signal_child ); | 1: table of all signal handlers
sigprocmask( SIG_BLOCK, &set, NULL ); |
| Returns on Lua stack:
signal( SIGHUP, signal_handler ); |
signal( SIGTERM, signal_handler ); | true if the signal could be registered with the kernel/libc
signal( SIGINT, signal_handler ); | false if they denied it
}
*/ */
int
l_onsignal( lua_State *L )
{
int sigc = 0;
int ok;
// the block mask includes all signals that have registered handlers.
// it is used to block all signals outside the select() call
// and also during the core signal handler runs.
sigset_t blockmask;
sigemptyset( &blockmask );
sigaddset( &blockmask, SIGCHLD );
// first time iterates the signal handler table to build
// the blockmask
lua_pushnil( L );
while( lua_next( L, -2 ) )
{
int htype = lua_type( L, -1 ); // the handle
// pops the value, leaves the key on stack
lua_pop( L, 1 );
// not a handler function (probably false)
if( htype != LUA_TFUNCTION ) continue;
int signum = lua_tointegerx( L, -1 , &ok );
if( !ok ) continue;
sigc++;
}
// and block those signals
sigprocmask( SIG_BLOCK, &blockmask, NULL );
// if there are more signal handlers than
// the signal queue allows, it is enlarged.
if( sigc >= queue_len )
{
while( sigc >= queue_len ) queue_len *= 2;
queue = s_realloc( (sig_atomic_t *)( queue ), queue_len * sizeof( sig_atomic_t ) );
}
// now iterates the signal handler table
// once again to register the signal handlers.
struct sigaction act;
memset (&act, '\0', sizeof(act));
act.sa_mask = blockmask;
lua_pushnil( L );
while( lua_next( L, -2 ) )
{
int htype = lua_type( L, -1 ); // the handle
act.sa_handler = &signal_handler;
// pops the value, leaves the key on stack
lua_pop( L, 1 );
// not a handler function (probably false)
if( htype != LUA_TFUNCTION ) continue;
int signum = lua_tointegerx( L, -1 , &ok );
if( !ok ) continue;
sigaction( signum, &act, 0 );
}
return 0;
}

View File

@ -18,4 +18,7 @@ extern volatile sig_atomic_t sigcode;
// Initializes signal handling. // Initializes signal handling.
extern void signal_init( ); extern void signal_init( );
// FIXME
int l_onsignal( lua_State *L );
#endif #endif

View File

@ -244,12 +244,6 @@ function mci.configure(
args, -- arguments given by user args, -- arguments given by user
monitors -- list of monitors the core can do monitors -- list of monitors the core can do
) )
print( "mci.configure", #args )
for k, v in pairs( args ) do
print( 'a', k, v )
end
Monitor.initialize( monitors ) Monitor.initialize( monitors )
-- --
@ -268,10 +262,7 @@ function mci.configure(
delay = delay =
{ {
1, 1,
function function( secs )
(
secs
)
clSettings.delay = secs + 0 clSettings.delay = secs + 0
end end
}, },
@ -281,10 +272,7 @@ function mci.configure(
logfile = logfile =
{ {
1, 1,
function function( file )
(
file
)
clSettings.logfile = file clSettings.logfile = file
end end
}, },
@ -292,8 +280,7 @@ function mci.configure(
version = version =
{ {
0, 0,
function function( )
( )
io.stdout:write( 'Version: ', lsyncd_version, '\n' ) io.stdout:write( 'Version: ', lsyncd_version, '\n' )
os.exit( 0 ) os.exit( 0 )

View File

@ -25,17 +25,27 @@ end
-- a table of all registered signal handlers -- a table of all registered signal handlers
local sigHandlers = { } --
-- keys are signal numbers
-- values are functions to be called
-- or 'false' in case of disabled default signals
--
-- On signal the core will directly look up this table.
mci.sigHandlers = { }
-- counter of signal handlers -- counter of signal handlers
-- used to tell the core to enlarge the signal queue if needed -- used to tell the core to enlarge the signal queue if needed
-- (the queue must be as large as the number of different signals listened for) -- (the queue must be as large as the number of different signals listened for)
local sigHandlerCount = 0 local sigHandlerCount = 0
-- --
-- onsignal function exported to userEnv -- Prepares an onsignal handle.
-- It changes the mantle data, but does not yet tell the core about it.
-- --
function onsignal -- To be used only internally to combine multiple changes into one.
--
local function onsignalPrep
( (
signal, -- signal number or name signal, -- signal number or name
handler -- function to call handler -- function to call
@ -52,12 +62,10 @@ function onsignal
then then
error( 'signal ' .. signal .. ' is an invalid number.' , 2 ) error( 'signal ' .. signal .. ' is an invalid number.' , 2 )
end end
signum = signal signum = 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.' , 2 )
@ -66,10 +74,22 @@ function onsignal
error( 'signal of type ' .. type( signal ) .. ' invalid.', 2 ) error( 'signal of type ' .. type( signal ) .. ' invalid.', 2 )
end end
-- FIXME store the handler in a table mci.sigHandlers[ signum ] = handler
-- FIXME tell core of max queue size end
core.onsignal( signum, handler ); --
-- 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
)
onsignalPrep( signal, handler )
core.onsignal( mci.sigHandlers )
end end
@ -82,24 +102,27 @@ function initSignalHandlers
( (
firstTime --- TODO check if needed firstTime --- TODO check if needed
) )
onsignal( onsignalPrep(
'HUP', 'HUP',
function( ) function( )
console.log( 'GOT A HUP SIGNAL' ); console.log( 'GOT A HUP SIGNAL' );
end end
) )
onsignal( onsignalPrep(
'INT', 'INT',
function( ) function( )
console.log( 'GOT A INT SIGNAL' ); console.log( 'GOT A INT SIGNAL' );
end end
) )
onsignal( onsignalPrep(
'TERM', 'TERM',
function( ) function( )
console.log( 'GOT A TERM SIGNAL' ); console.log( 'GOT A TERM SIGNAL' );
end end
) )
core.onsignal( mci.sigHandlers )
end end