diff options
-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 |