diff --git a/CMakeLists.txt b/CMakeLists.txt index 74a54af..3f0e7d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,10 +65,10 @@ set( MANTLE_CODE ${PROJECT_SOURCE_DIR}/mantle/syncmaster.lua ${PROJECT_SOURCE_DIR}/mantle/monitor.lua ${PROJECT_SOURCE_DIR}/mantle/fwriter.lua - ${PROJECT_SOURCE_DIR}/mantle/signal.lua ${PROJECT_SOURCE_DIR}/mantle/statusfile.lua ${PROJECT_SOURCE_DIR}/mantle/useralarm.lua ${PROJECT_SOURCE_DIR}/mantle/mci.lua + ${PROJECT_SOURCE_DIR}/mantle/signal.lua ${PROJECT_SOURCE_DIR}/mantle/user.lua ${PROJECT_SOURCE_DIR}/mantle/string.lua ${PROJECT_SOURCE_DIR}/mantle/version.lua diff --git a/core/mci.c b/core/mci.c index 60f13e0..f8e7b55 100644 --- a/core/mci.c +++ b/core/mci.c @@ -460,6 +460,7 @@ l_stackdump( lua_State * L ) return 0; } + /* | Reads the directories entries. | @@ -650,7 +651,7 @@ static const luaL_Reg corelib[ ] = { "now", l_now }, { "nonobserve_fd", l_nonobserve_fd }, { "observe_fd", l_observe_fd }, -// { "onsignal", l_onsignal }, + { "onsignal", l_onsignal }, { "readdir", l_readdir }, { "realdir", l_realdir }, { "stackdump", l_stackdump }, diff --git a/core/mem.c b/core/mem.c index 9fdcfd8..4000305 100644 --- a/core/mem.c +++ b/core/mem.c @@ -27,7 +27,7 @@ #include "log.h" /* -| "Secured" calloc +| "Secured" calloc. */ extern void * s_calloc( size_t nmemb, size_t size ) @@ -63,7 +63,7 @@ s_malloc( size_t size ) /* -| "Secured" realloc +| "Secured" realloc. */ extern void * s_realloc( void * ptr, size_t size ) @@ -81,7 +81,7 @@ s_realloc( void * ptr, size_t size ) /* -| "Secured" strdup +| "Secured" strdup. */ extern char * s_strdup( const char *src ) diff --git a/core/observe.c b/core/observe.c index 4466912..382640d 100644 --- a/core/observe.c +++ b/core/observe.c @@ -240,11 +240,12 @@ observe_select // that puts Lsyncd to sleep until anything worth noticing // happens - pr = pselect( - observances[ observances_len - 1 ].fd + 1, - &rfds, &wfds, NULL, - timeout, &sigset - ); + pr = + pselect( + observances[ observances_len - 1 ].fd + 1, + &rfds, &wfds, NULL, + timeout, &sigset + ); // FIXME handle signals diff --git a/core/signal.c b/core/signal.c index 644a828..2f94dc7 100644 --- a/core/signal.c +++ b/core/signal.c @@ -10,7 +10,9 @@ */ #include "feature.h" +#include #include +#include #include #include @@ -19,6 +21,7 @@ #include #include +#include "log.h" #include "mem.h" @@ -26,13 +29,6 @@ static volatile sig_atomic_t * queue; static int queue_len; static int queue_pos; -/* -| XXX -*/ -static int *handlers; -static int handlers_len; -static int handlers_maxlen; - /* | Set by TERM or HUP signal handler @@ -49,7 +45,8 @@ volatile sig_atomic_t sigcode = 0; /* | signal handler */ -static void signal_child( int sig ) +static void +signal_child( int sig ) { // Nothing! // @@ -64,23 +61,24 @@ static void signal_child( int sig ) static void signal_handler( int sig ) { - switch( sig ) + // looks if this signal is already queued + for( int i = 0; i < queue_pos; i++ ) { - case SIGTERM: - case SIGINT: - term = 1; - sigcode = sig; - return; - - case SIGHUP: - hup = 1; - return; + // if so it is dropped + if( queue[ i ] == sig ) 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. | @@ -93,22 +91,90 @@ signal_init( ) queue_len = 5; queue = s_malloc( queue_len * sizeof( sig_atomic_t ) ); queue_pos = 0; - - handlers_maxlen = 5; - handlers_len = 0; - handlers = s_malloc( handlers_maxlen * sizeof( int * ) ); } + /* - sigset_t set; - sigemptyset( &set ); - sigaddset( &set, SIGCHLD ); - signal( SIGCHLD, signal_child ); - sigprocmask( SIG_BLOCK, &set, NULL ); - - signal( SIGHUP, signal_handler ); - signal( SIGTERM, signal_handler ); - signal( SIGINT, signal_handler ); -} +| Registers (or deregisters) a signal handlers. +| +| Params on Lua stack: +| 1: table of all signal handlers +| +| Returns on Lua stack: +| +| true if the signal could be registered with the kernel/libc +| 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; +} diff --git a/core/signal.h b/core/signal.h index d9e00d0..885d5d3 100644 --- a/core/signal.h +++ b/core/signal.h @@ -18,4 +18,7 @@ extern volatile sig_atomic_t sigcode; // Initializes signal handling. extern void signal_init( ); +// FIXME +int l_onsignal( lua_State *L ); + #endif diff --git a/mantle/mci.lua b/mantle/mci.lua index d241615..b411456 100644 --- a/mantle/mci.lua +++ b/mantle/mci.lua @@ -244,12 +244,6 @@ function mci.configure( args, -- arguments given by user 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 ) -- @@ -268,10 +262,7 @@ function mci.configure( delay = { 1, - function - ( - secs - ) + function( secs ) clSettings.delay = secs + 0 end }, @@ -281,10 +272,7 @@ function mci.configure( logfile = { 1, - function - ( - file - ) + function( file ) clSettings.logfile = file end }, @@ -292,8 +280,7 @@ function mci.configure( version = { 0, - function - ( ) + function( ) io.stdout:write( 'Version: ', lsyncd_version, '\n' ) os.exit( 0 ) diff --git a/mantle/signal.lua b/mantle/signal.lua index 2b00f5b..b593b74 100644 --- a/mantle/signal.lua +++ b/mantle/signal.lua @@ -25,17 +25,27 @@ end -- 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 -- 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) 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 handler -- function to call @@ -52,12 +62,10 @@ function onsignal then error( 'signal ' .. signal .. ' is an invalid number.' , 2 ) end - signum = signal elseif type( signal ) == 'string' then signum = signums[ signal ] - if signum == nil then error( 'signal "' .. signal .. '" unknown.' , 2 ) @@ -66,10 +74,22 @@ function onsignal error( 'signal of type ' .. type( signal ) .. ' invalid.', 2 ) end - -- FIXME store the handler in a table - -- FIXME tell core of max queue size + mci.sigHandlers[ signum ] = handler +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 @@ -82,24 +102,27 @@ function initSignalHandlers ( firstTime --- TODO check if needed ) - onsignal( + onsignalPrep( 'HUP', function( ) console.log( 'GOT A HUP SIGNAL' ); end ) - onsignal( + onsignalPrep( 'INT', function( ) console.log( 'GOT A INT SIGNAL' ); end ) - onsignal( + onsignalPrep( 'TERM', function( ) console.log( 'GOT A TERM SIGNAL' ); end ) + + core.onsignal( mci.sigHandlers ) end +