diff options
| author | Benoit Germain <bnt period germain arrobase gmail period com> | 2013-12-20 11:47:38 +0100 |
|---|---|---|
| committer | Benoit Germain <bnt period germain arrobase gmail period com> | 2013-12-20 11:47:38 +0100 |
| commit | 95c696cffe7bf16e27d6d766750c96a38dd23b32 (patch) | |
| tree | c12099fbff87a330bc0998ec6961c97e03c1c8f2 /src | |
| parent | 4ece73b1e0d8f75fa63a5b39a91731147870bd0a (diff) | |
| download | lanes-95c696cffe7bf16e27d6d766750c96a38dd23b32.tar.gz lanes-95c696cffe7bf16e27d6d766750c96a38dd23b32.tar.bz2 lanes-95c696cffe7bf16e27d6d766750c96a38dd23b32.zip | |
fixed a shutdown crash
* fixed a crash that can occur at shutdown when an object stored inside
a keeper state performs a linda operation on a linda making use of
another keeper
* bumped version to 3.7.5
Diffstat (limited to 'src')
| -rw-r--r-- | src/keeper.c | 16 | ||||
| -rw-r--r-- | src/lanes.c | 25 |
2 files changed, 26 insertions, 15 deletions
diff --git a/src/keeper.c b/src/keeper.c index 99f510b..4c90069 100644 --- a/src/keeper.c +++ b/src/keeper.c | |||
| @@ -184,7 +184,8 @@ static void push_table( lua_State* L, int idx) | |||
| 184 | int keeper_push_linda_storage( lua_State* L, void* ptr) | 184 | int keeper_push_linda_storage( lua_State* L, void* ptr) |
| 185 | { | 185 | { |
| 186 | struct s_Keeper* K = keeper_acquire( ptr); | 186 | struct s_Keeper* K = keeper_acquire( ptr); |
| 187 | lua_State* KL = K->L; | 187 | lua_State* KL = K ? K->L : NULL; |
| 188 | if( KL == NULL) return 0; | ||
| 188 | STACK_CHECK( KL); | 189 | STACK_CHECK( KL); |
| 189 | lua_pushlightuserdata( KL, fifos_key); // fifos_key | 190 | lua_pushlightuserdata( KL, fifos_key); // fifos_key |
| 190 | lua_rawget( KL, LUA_REGISTRYINDEX); // fifos | 191 | lua_rawget( KL, LUA_REGISTRYINDEX); // fifos |
| @@ -535,14 +536,18 @@ void close_keepers( void) | |||
| 535 | #endif // HAVE_KEEPER_ATEXIT_DESINIT | 536 | #endif // HAVE_KEEPER_ATEXIT_DESINIT |
| 536 | { | 537 | { |
| 537 | int i; | 538 | int i; |
| 538 | // 2-pass close, in case a keeper holds a reference to a linda bound to another keeoer | 539 | int const nbKeepers = GNbKeepers; |
| 539 | for( i = 0; i < GNbKeepers; ++ i) | 540 | // NOTE: imagine some keeper state N+1 currently holds a linda that uses another keeper N, and a _gc that will make use of it |
| 541 | // when keeper N+1 is closed, object is GCed, linda operation is called, which attempts to acquire keeper N, whose Lua state no longer exists | ||
| 542 | // in that case, the linda operation should do nothing. which means that these operations must check for keeper acquisition success | ||
| 543 | GNbKeepers = 0; | ||
| 544 | for( i = 0; i < nbKeepers; ++ i) | ||
| 540 | { | 545 | { |
| 541 | lua_State* L = GKeepers[i].L; | 546 | lua_State* L = GKeepers[i].L; |
| 542 | GKeepers[i].L = NULL; | 547 | GKeepers[i].L = NULL; |
| 543 | lua_close( L); | 548 | lua_close( L); |
| 544 | } | 549 | } |
| 545 | for( i = 0; i < GNbKeepers; ++ i) | 550 | for( i = 0; i < nbKeepers; ++ i) |
| 546 | { | 551 | { |
| 547 | MUTEX_FREE( &GKeepers[i].lock_); | 552 | MUTEX_FREE( &GKeepers[i].lock_); |
| 548 | } | 553 | } |
| @@ -551,7 +556,6 @@ void close_keepers( void) | |||
| 551 | free( GKeepers); | 556 | free( GKeepers); |
| 552 | } | 557 | } |
| 553 | GKeepers = NULL; | 558 | GKeepers = NULL; |
| 554 | GNbKeepers = 0; | ||
| 555 | } | 559 | } |
| 556 | 560 | ||
| 557 | /* | 561 | /* |
| @@ -626,7 +630,7 @@ struct s_Keeper* keeper_acquire( void const* ptr) | |||
| 626 | * have to cast to unsigned long to avoid compilation warnings about loss of data when converting pointer-to-integer | 630 | * have to cast to unsigned long to avoid compilation warnings about loss of data when converting pointer-to-integer |
| 627 | */ | 631 | */ |
| 628 | unsigned int i = (unsigned int)(((unsigned long)(ptr) >> 3) % GNbKeepers); | 632 | unsigned int i = (unsigned int)(((unsigned long)(ptr) >> 3) % GNbKeepers); |
| 629 | struct s_Keeper *K= &GKeepers[i]; | 633 | struct s_Keeper* K= &GKeepers[i]; |
| 630 | 634 | ||
| 631 | MUTEX_LOCK( &K->lock_); | 635 | MUTEX_LOCK( &K->lock_); |
| 632 | //++ K->count; | 636 | //++ K->count; |
diff --git a/src/lanes.c b/src/lanes.c index 6621735..e66342d 100644 --- a/src/lanes.c +++ b/src/lanes.c | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | * ... | 52 | * ... |
| 53 | */ | 53 | */ |
| 54 | 54 | ||
| 55 | char const* VERSION = "3.7.4"; | 55 | char const* VERSION = "3.7.5"; |
| 56 | 56 | ||
| 57 | /* | 57 | /* |
| 58 | =============================================================================== | 58 | =============================================================================== |
| @@ -420,7 +420,8 @@ LUAG_FUNC( linda_send) | |||
| 420 | STACK_GROW(L, 1); | 420 | STACK_GROW(L, 1); |
| 421 | { | 421 | { |
| 422 | struct s_Keeper* K = keeper_acquire( linda); | 422 | struct s_Keeper* K = keeper_acquire( linda); |
| 423 | lua_State* KL = K->L; // need to do this for 'STACK_CHECK' | 423 | lua_State* KL = K ? K->L : NULL; // need to do this for 'STACK_CHECK' |
| 424 | if( KL == NULL) return 0; | ||
| 424 | STACK_CHECK( KL); | 425 | STACK_CHECK( KL); |
| 425 | for( ;;) | 426 | for( ;;) |
| 426 | { | 427 | { |
| @@ -584,6 +585,7 @@ LUAG_FUNC( linda_receive) | |||
| 584 | 585 | ||
| 585 | { | 586 | { |
| 586 | struct s_Keeper *K = keeper_acquire( linda); | 587 | struct s_Keeper *K = keeper_acquire( linda); |
| 588 | if( K == NULL) return 0; | ||
| 587 | for( ;;) | 589 | for( ;;) |
| 588 | { | 590 | { |
| 589 | // all arguments of receive() but the first are passed to the keeper's receive function | 591 | // all arguments of receive() but the first are passed to the keeper's receive function |
| @@ -690,6 +692,7 @@ LUAG_FUNC( linda_set) | |||
| 690 | { | 692 | { |
| 691 | int pushed; | 693 | int pushed; |
| 692 | struct s_Keeper *K = keeper_acquire( linda); | 694 | struct s_Keeper *K = keeper_acquire( linda); |
| 695 | if( K == NULL) return 0; | ||
| 693 | // no nil->sentinel toggling, we really clear the linda contents for the given key with a set() | 696 | // no nil->sentinel toggling, we really clear the linda contents for the given key with a set() |
| 694 | pushed = keeper_call( K->L, KEEPER_API( set), L, linda, 2); | 697 | pushed = keeper_call( K->L, KEEPER_API( set), L, linda, 2); |
| 695 | if( pushed >= 0) // no error? | 698 | if( pushed >= 0) // no error? |
| @@ -722,7 +725,7 @@ LUAG_FUNC( linda_set) | |||
| 722 | */ | 725 | */ |
| 723 | LUAG_FUNC( linda_count) | 726 | LUAG_FUNC( linda_count) |
| 724 | { | 727 | { |
| 725 | struct s_Linda *linda= lua_toLinda( L, 1); | 728 | struct s_Linda* linda = lua_toLinda( L, 1); |
| 726 | int pushed; | 729 | int pushed; |
| 727 | 730 | ||
| 728 | luaL_argcheck( L, linda, 1, "expected a linda object!"); | 731 | luaL_argcheck( L, linda, 1, "expected a linda object!"); |
| @@ -730,7 +733,8 @@ LUAG_FUNC( linda_count) | |||
| 730 | check_key_types( L, 2, lua_gettop( L)); | 733 | check_key_types( L, 2, lua_gettop( L)); |
| 731 | 734 | ||
| 732 | { | 735 | { |
| 733 | struct s_Keeper *K = keeper_acquire( linda); | 736 | struct s_Keeper* K = keeper_acquire( linda); |
| 737 | if( K == NULL) return 0; | ||
| 734 | pushed = keeper_call( K->L, KEEPER_API( count), L, linda, 2); | 738 | pushed = keeper_call( K->L, KEEPER_API( count), L, linda, 2); |
| 735 | keeper_release( K); | 739 | keeper_release( K); |
| 736 | if( pushed < 0) | 740 | if( pushed < 0) |
| @@ -758,14 +762,15 @@ LUAG_FUNC( linda_get) | |||
| 758 | check_key_types( L, 2, 2); | 762 | check_key_types( L, 2, 2); |
| 759 | 763 | ||
| 760 | { | 764 | { |
| 761 | struct s_Keeper *K = keeper_acquire( linda); | 765 | struct s_Keeper* K = keeper_acquire( linda); |
| 766 | if( K == NULL) return 0; | ||
| 762 | pushed = keeper_call( K->L, KEEPER_API( get), L, linda, 2); | 767 | pushed = keeper_call( K->L, KEEPER_API( get), L, linda, 2); |
| 763 | ASSERT_L( pushed==0 || pushed==1 ); | 768 | ASSERT_L( pushed == 0 || pushed == 1); |
| 764 | if( pushed > 0) | 769 | if( pushed > 0) |
| 765 | { | 770 | { |
| 766 | keeper_toggle_nil_sentinels( L, lua_gettop( L) - pushed, 0); | 771 | keeper_toggle_nil_sentinels( L, lua_gettop( L) - pushed, 0); |
| 767 | } | 772 | } |
| 768 | keeper_release(K); | 773 | keeper_release( K); |
| 769 | // must trigger error after keeper state has been released | 774 | // must trigger error after keeper state has been released |
| 770 | if( pushed < 0) | 775 | if( pushed < 0) |
| 771 | { | 776 | { |
| @@ -784,7 +789,8 @@ LUAG_FUNC( linda_get) | |||
| 784 | */ | 789 | */ |
| 785 | LUAG_FUNC( linda_limit) | 790 | LUAG_FUNC( linda_limit) |
| 786 | { | 791 | { |
| 787 | struct s_Linda* linda= lua_toLinda( L, 1 ); | 792 | struct s_Linda* linda= lua_toLinda( L, 1); |
| 793 | int pushed; | ||
| 788 | 794 | ||
| 789 | luaL_argcheck( L, linda, 1, "expected a linda object!"); | 795 | luaL_argcheck( L, linda, 1, "expected a linda object!"); |
| 790 | // make sure we got a key and a limit | 796 | // make sure we got a key and a limit |
| @@ -796,7 +802,8 @@ LUAG_FUNC( linda_limit) | |||
| 796 | 802 | ||
| 797 | { | 803 | { |
| 798 | struct s_Keeper* K = keeper_acquire( linda); | 804 | struct s_Keeper* K = keeper_acquire( linda); |
| 799 | int pushed = keeper_call( K->L, KEEPER_API( limit), L, linda, 2); | 805 | if( K == NULL) return 0; |
| 806 | pushed = keeper_call( K->L, KEEPER_API( limit), L, linda, 2); | ||
| 800 | ASSERT_L( pushed <= 0); // either error or no return values | 807 | ASSERT_L( pushed <= 0); // either error or no return values |
| 801 | keeper_release( K); | 808 | keeper_release( K); |
| 802 | // must trigger error after keeper state has been released | 809 | // must trigger error after keeper state has been released |
