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