From 32aa7012099d6a4b714aef27ab9dbacbdb728c1f Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Fri, 10 Aug 2012 08:28:11 +0200 Subject: fix possible crash at application shutdown when a race condition causes linda objects to be collected after the keeper states are cleaned up. --- CHANGES | 3 +++ src/keeper.c | 33 ++++++++++++++++++--------------- src/keeper.h | 1 - src/lanes.c | 6 ++---- src/lanes.lua | 2 +- 5 files changed, 24 insertions(+), 21 deletions(-) diff --git a/CHANGES b/CHANGES index f6f5268..b2882e7 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,8 @@ CHANGES: +CHANGE 43: BGe 09-Aug-2012 + * fix possible crash at application shutdown when a race condition causes linda objects to be collected after the keeper states are cleaned up. + CHANGE 42: BGe 06-Aug-2012 * lanes.linda() accepts an optional name for debug purposes diff --git a/src/keeper.c b/src/keeper.c index 2404520..28dc338 100644 --- a/src/keeper.c +++ b/src/keeper.c @@ -63,6 +63,21 @@ static struct s_Keeper *GKeepers = NULL; static int GNbKeepers = 0; +static void atexit_close_keepers(void) +{ + int i; + for( i = 0; i < GNbKeepers; ++ i) + { + lua_close( GKeepers[i].L); + GKeepers[i].L = 0; + //assert( GKeepers[i].count == 0); + MUTEX_FREE( &GKeepers[i].lock_); + } + if( GKeepers) free( GKeepers); + GKeepers = NULL; + GNbKeepers = 0; +} + /* * Initialize keeper states * @@ -118,6 +133,9 @@ char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create) GKeepers[i].L = K; //GKeepers[i].count = 0; } + // call close_keepers at the very last as we want to be sure no thread is GCing after. + // (and therefore may perform linda object dereferencing after keepers are gone) + atexit( atexit_close_keepers); return NULL; // ok } @@ -264,18 +282,3 @@ int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda, lua_settop( K, Ktos); return retvals; } - -void close_keepers(void) -{ - int i; - for( i = 0; i < GNbKeepers; ++ i) - { - lua_close( GKeepers[i].L); - GKeepers[i].L = 0; - //assert( GKeepers[i].count == 0); - MUTEX_FREE( &GKeepers[i].lock_); - } - if( GKeepers) free( GKeepers); - GKeepers = NULL; - GNbKeepers = 0; -} diff --git a/src/keeper.h b/src/keeper.h index 0990846..6c4c6f9 100644 --- a/src/keeper.h +++ b/src/keeper.h @@ -14,7 +14,6 @@ struct s_Keeper *keeper_acquire( const void *ptr); void keeper_release( struct s_Keeper *K); void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel); int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda, uint_t starting_index); -void close_keepers(void); #endif // __keeper_h__ \ No newline at end of file diff --git a/src/lanes.c b/src/lanes.c index b65c6fa..262a497 100644 --- a/src/lanes.c +++ b/src/lanes.c @@ -1070,7 +1070,7 @@ volatile DEEP_PRELUDE *timer_deep; // = NULL /* * Process end; cancel any still free-running threads */ -static int selfdestruct_atexit( lua_State *L) +static int selfdestruct_gc( lua_State *L) { (void)L; // unused if (selfdestruct_first == SELFDESTRUCT_END) return 0; // no free-running threads @@ -1214,7 +1214,6 @@ static int selfdestruct_atexit( lua_State *L) DEBUGEXEC(fprintf( stderr, "Killed %d lane(s) at process end.\n", n )); #endif } - close_keepers(); return 0; } @@ -2363,7 +2362,6 @@ static void init_once_LOCKED( lua_State* L, volatile DEEP_PRELUDE** timer_deep_r // Selfdestruct chain handling // MUTEX_INIT( &selfdestruct_cs ); - //atexit( selfdestruct_atexit ); //--- // Linux needs SCHED_RR to change thread priorities, and that is only @@ -2421,7 +2419,7 @@ static void init_once_LOCKED( lua_State* L, volatile DEEP_PRELUDE** timer_deep_r { lua_newuserdata( L, 1); lua_newtable( L); - lua_pushcfunction( L, selfdestruct_atexit); + lua_pushcfunction( L, selfdestruct_gc); lua_setfield( L, -2, "__gc"); lua_pushliteral( L, "AtExit"); lua_setfield( L, -2, "__metatable"); diff --git a/src/lanes.lua b/src/lanes.lua index 8cd3737..e6400df 100644 --- a/src/lanes.lua +++ b/src/lanes.lua @@ -255,7 +255,7 @@ end -- We let the C code attach methods to userdata directly ----- --- lanes.linda() -> linda_ud +-- lanes.linda(["name"]) -> linda_ud -- -- PUBLIC LANES API local linda = mm.linda -- cgit v1.2.3-55-g6feb