diff options
| author | Benoit Germain <bnt.germain@gmail.com> | 2012-08-10 08:28:11 +0200 |
|---|---|---|
| committer | Benoit Germain <bnt.germain@gmail.com> | 2012-08-10 08:28:11 +0200 |
| commit | 32aa7012099d6a4b714aef27ab9dbacbdb728c1f (patch) | |
| tree | e6408603a0b07324dcd0cdc189558eafad320785 | |
| parent | 41b4da54f25d9870b5a0a965815be1e3c1578e80 (diff) | |
| download | lanes-32aa7012099d6a4b714aef27ab9dbacbdb728c1f.tar.gz lanes-32aa7012099d6a4b714aef27ab9dbacbdb728c1f.tar.bz2 lanes-32aa7012099d6a4b714aef27ab9dbacbdb728c1f.zip | |
fix possible crash at application shutdown when a race condition causes linda objects to be collected after the keeper states are cleaned up.
| -rw-r--r-- | CHANGES | 3 | ||||
| -rw-r--r-- | src/keeper.c | 33 | ||||
| -rw-r--r-- | src/keeper.h | 1 | ||||
| -rw-r--r-- | src/lanes.c | 6 | ||||
| -rw-r--r-- | src/lanes.lua | 2 |
5 files changed, 24 insertions, 21 deletions
| @@ -1,5 +1,8 @@ | |||
| 1 | CHANGES: | 1 | CHANGES: |
| 2 | 2 | ||
| 3 | CHANGE 43: BGe 09-Aug-2012 | ||
| 4 | * fix possible crash at application shutdown when a race condition causes linda objects to be collected after the keeper states are cleaned up. | ||
| 5 | |||
| 3 | CHANGE 42: BGe 06-Aug-2012 | 6 | CHANGE 42: BGe 06-Aug-2012 |
| 4 | * lanes.linda() accepts an optional name for debug purposes | 7 | * lanes.linda() accepts an optional name for debug purposes |
| 5 | 8 | ||
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 @@ | |||
| 63 | static struct s_Keeper *GKeepers = NULL; | 63 | static struct s_Keeper *GKeepers = NULL; |
| 64 | static int GNbKeepers = 0; | 64 | static int GNbKeepers = 0; |
| 65 | 65 | ||
| 66 | static void atexit_close_keepers(void) | ||
| 67 | { | ||
| 68 | int i; | ||
| 69 | for( i = 0; i < GNbKeepers; ++ i) | ||
| 70 | { | ||
| 71 | lua_close( GKeepers[i].L); | ||
| 72 | GKeepers[i].L = 0; | ||
| 73 | //assert( GKeepers[i].count == 0); | ||
| 74 | MUTEX_FREE( &GKeepers[i].lock_); | ||
| 75 | } | ||
| 76 | if( GKeepers) free( GKeepers); | ||
| 77 | GKeepers = NULL; | ||
| 78 | GNbKeepers = 0; | ||
| 79 | } | ||
| 80 | |||
| 66 | /* | 81 | /* |
| 67 | * Initialize keeper states | 82 | * Initialize keeper states |
| 68 | * | 83 | * |
| @@ -118,6 +133,9 @@ char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create) | |||
| 118 | GKeepers[i].L = K; | 133 | GKeepers[i].L = K; |
| 119 | //GKeepers[i].count = 0; | 134 | //GKeepers[i].count = 0; |
| 120 | } | 135 | } |
| 136 | // call close_keepers at the very last as we want to be sure no thread is GCing after. | ||
| 137 | // (and therefore may perform linda object dereferencing after keepers are gone) | ||
| 138 | atexit( atexit_close_keepers); | ||
| 121 | return NULL; // ok | 139 | return NULL; // ok |
| 122 | } | 140 | } |
| 123 | 141 | ||
| @@ -264,18 +282,3 @@ int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda, | |||
| 264 | lua_settop( K, Ktos); | 282 | lua_settop( K, Ktos); |
| 265 | return retvals; | 283 | return retvals; |
| 266 | } | 284 | } |
| 267 | |||
| 268 | void close_keepers(void) | ||
| 269 | { | ||
| 270 | int i; | ||
| 271 | for( i = 0; i < GNbKeepers; ++ i) | ||
| 272 | { | ||
| 273 | lua_close( GKeepers[i].L); | ||
| 274 | GKeepers[i].L = 0; | ||
| 275 | //assert( GKeepers[i].count == 0); | ||
| 276 | MUTEX_FREE( &GKeepers[i].lock_); | ||
| 277 | } | ||
| 278 | if( GKeepers) free( GKeepers); | ||
| 279 | GKeepers = NULL; | ||
| 280 | GNbKeepers = 0; | ||
| 281 | } | ||
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); | |||
| 14 | void keeper_release( struct s_Keeper *K); | 14 | void keeper_release( struct s_Keeper *K); |
| 15 | void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel); | 15 | void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel); |
| 16 | int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda, uint_t starting_index); | 16 | int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda, uint_t starting_index); |
| 17 | void close_keepers(void); | ||
| 18 | 17 | ||
| 19 | 18 | ||
| 20 | #endif // __keeper_h__ \ No newline at end of file | 19 | #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 | |||
| 1070 | /* | 1070 | /* |
| 1071 | * Process end; cancel any still free-running threads | 1071 | * Process end; cancel any still free-running threads |
| 1072 | */ | 1072 | */ |
| 1073 | static int selfdestruct_atexit( lua_State *L) | 1073 | static int selfdestruct_gc( lua_State *L) |
| 1074 | { | 1074 | { |
| 1075 | (void)L; // unused | 1075 | (void)L; // unused |
| 1076 | if (selfdestruct_first == SELFDESTRUCT_END) return 0; // no free-running threads | 1076 | if (selfdestruct_first == SELFDESTRUCT_END) return 0; // no free-running threads |
| @@ -1214,7 +1214,6 @@ static int selfdestruct_atexit( lua_State *L) | |||
| 1214 | DEBUGEXEC(fprintf( stderr, "Killed %d lane(s) at process end.\n", n )); | 1214 | DEBUGEXEC(fprintf( stderr, "Killed %d lane(s) at process end.\n", n )); |
| 1215 | #endif | 1215 | #endif |
| 1216 | } | 1216 | } |
| 1217 | close_keepers(); | ||
| 1218 | return 0; | 1217 | return 0; |
| 1219 | } | 1218 | } |
| 1220 | 1219 | ||
| @@ -2363,7 +2362,6 @@ static void init_once_LOCKED( lua_State* L, volatile DEEP_PRELUDE** timer_deep_r | |||
| 2363 | // Selfdestruct chain handling | 2362 | // Selfdestruct chain handling |
| 2364 | // | 2363 | // |
| 2365 | MUTEX_INIT( &selfdestruct_cs ); | 2364 | MUTEX_INIT( &selfdestruct_cs ); |
| 2366 | //atexit( selfdestruct_atexit ); | ||
| 2367 | 2365 | ||
| 2368 | //--- | 2366 | //--- |
| 2369 | // Linux needs SCHED_RR to change thread priorities, and that is only | 2367 | // 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 | |||
| 2421 | { | 2419 | { |
| 2422 | lua_newuserdata( L, 1); | 2420 | lua_newuserdata( L, 1); |
| 2423 | lua_newtable( L); | 2421 | lua_newtable( L); |
| 2424 | lua_pushcfunction( L, selfdestruct_atexit); | 2422 | lua_pushcfunction( L, selfdestruct_gc); |
| 2425 | lua_setfield( L, -2, "__gc"); | 2423 | lua_setfield( L, -2, "__gc"); |
| 2426 | lua_pushliteral( L, "AtExit"); | 2424 | lua_pushliteral( L, "AtExit"); |
| 2427 | lua_setfield( L, -2, "__metatable"); | 2425 | 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 | |||
| 255 | -- We let the C code attach methods to userdata directly | 255 | -- We let the C code attach methods to userdata directly |
| 256 | 256 | ||
| 257 | ----- | 257 | ----- |
| 258 | -- lanes.linda() -> linda_ud | 258 | -- lanes.linda(["name"]) -> linda_ud |
| 259 | -- | 259 | -- |
| 260 | -- PUBLIC LANES API | 260 | -- PUBLIC LANES API |
| 261 | local linda = mm.linda | 261 | local linda = mm.linda |
