diff options
author | Benoit Germain <bnt period germain arrobase gmail period com> | 2014-02-18 09:56:23 +0100 |
---|---|---|
committer | Benoit Germain <bnt period germain arrobase gmail period com> | 2014-02-18 09:56:23 +0100 |
commit | 48517ca661895a0c70093e78f165866cb9363206 (patch) | |
tree | a440e16a69b0a85cdb5663ba181a1c3ac2bf0bc5 /src/keeper.c | |
parent | 5f092fe0ec8b6942c63262e7c14c7e4ba913b023 (diff) | |
download | lanes-48517ca661895a0c70093e78f165866cb9363206.tar.gz lanes-48517ca661895a0c70093e78f165866cb9363206.tar.bz2 lanes-48517ca661895a0c70093e78f165866cb9363206.zip |
Lanes init crash fix
* bumped version to 3.9.1
* keeper array is allocated with master state's alloc function instead
of malloc()/free()
* prevent application crash when specifying a very large number of
keepers in the configuration options
* removed some keeper desinit legacy dead code
* any error occuring during one-time inits is raised outside the
one-time mutex protected code region
Diffstat (limited to 'src/keeper.c')
-rw-r--r-- | src/keeper.c | 67 |
1 files changed, 42 insertions, 25 deletions
diff --git a/src/keeper.c b/src/keeper.c index 9b77c75..0f54e13 100644 --- a/src/keeper.c +++ b/src/keeper.c | |||
@@ -580,11 +580,7 @@ int keepercall_count( lua_State* L) | |||
580 | static struct s_Keeper *GKeepers = NULL; | 580 | static struct s_Keeper *GKeepers = NULL; |
581 | static int GNbKeepers = 0; | 581 | static int GNbKeepers = 0; |
582 | 582 | ||
583 | #if HAVE_KEEPER_ATEXIT_DESINIT | 583 | void close_keepers( lua_State* L) |
584 | static void atexit_close_keepers( void) | ||
585 | #else // HAVE_KEEPER_ATEXIT_DESINIT | ||
586 | void close_keepers( void) | ||
587 | #endif // HAVE_KEEPER_ATEXIT_DESINIT | ||
588 | { | 584 | { |
589 | int i; | 585 | int i; |
590 | int const nbKeepers = GNbKeepers; | 586 | int const nbKeepers = GNbKeepers; |
@@ -604,25 +600,29 @@ void close_keepers( void) | |||
604 | } | 600 | } |
605 | if( GKeepers != NULL) | 601 | if( GKeepers != NULL) |
606 | { | 602 | { |
607 | free( GKeepers); | 603 | void* allocUD; |
604 | lua_Alloc allocF = lua_getallocf( L, &allocUD); | ||
605 | allocF( allocUD, GKeepers, nbKeepers * sizeof( struct s_Keeper), 0); | ||
608 | } | 606 | } |
609 | GKeepers = NULL; | 607 | GKeepers = NULL; |
610 | } | 608 | } |
611 | 609 | ||
612 | /* | 610 | /* |
613 | * Initialize keeper states | 611 | * Initialize keeper states |
614 | * | 612 | * |
615 | * If there is a problem, return an error message (NULL for okay). | 613 | * If there is a problem, return an error message (NULL for okay). |
616 | * | 614 | * |
617 | * Note: Any problems would be design flaws; the created Lua state is left | 615 | * Note: Any problems would be design flaws; the created Lua state is left |
618 | * unclosed, because it does not really matter. In production code, this | 616 | * unclosed, because it does not really matter. In production code, this |
619 | * function never fails. | 617 | * function never fails. |
620 | * settings table is at position 1 on the stack | 618 | * settings table is at position 1 on the stack |
621 | */ | 619 | * pushes an error string on the stack in case of problem |
622 | char const* init_keepers( lua_State* L) | 620 | */ |
621 | int init_keepers( lua_State* L) | ||
623 | { | 622 | { |
624 | int i; | 623 | int i; |
625 | PROPAGATE_ALLOCF_PREP( L); | 624 | void* allocUD; |
625 | lua_Alloc allocF = lua_getallocf( L, &allocUD); | ||
626 | 626 | ||
627 | STACK_CHECK( L); // L K | 627 | STACK_CHECK( L); // L K |
628 | lua_getfield( L, 1, "nb_keepers"); // nb_keepers | 628 | lua_getfield( L, 1, "nb_keepers"); // nb_keepers |
@@ -630,13 +630,21 @@ char const* init_keepers( lua_State* L) | |||
630 | lua_pop( L, 1); // | 630 | lua_pop( L, 1); // |
631 | assert( GNbKeepers >= 1); | 631 | assert( GNbKeepers >= 1); |
632 | 632 | ||
633 | GKeepers = malloc( GNbKeepers * sizeof( struct s_Keeper)); | 633 | GKeepers = (struct s_Keeper*) allocF( allocUD, NULL, 0, GNbKeepers * sizeof( struct s_Keeper)); |
634 | if( GKeepers == NULL) | ||
635 | { | ||
636 | lua_pushliteral( L, "init_keepers() failed while creating keeper array; out of memory"); | ||
637 | STACK_MID( L, 1); | ||
638 | return 1; | ||
639 | } | ||
634 | for( i = 0; i < GNbKeepers; ++ i) | 640 | for( i = 0; i < GNbKeepers; ++ i) |
635 | { | 641 | { |
636 | lua_State* K = PROPAGATE_ALLOCF_ALLOC(); | 642 | lua_State* K = PROPAGATE_ALLOCF_ALLOC(); |
637 | if( K == NULL) | 643 | if( K == NULL) |
638 | { | 644 | { |
639 | (void) luaL_error( L, "init_keepers() failed while creating keeper state; out of memory"); | 645 | lua_pushliteral( L, "init_keepers() failed while creating keeper states; out of memory"); |
646 | STACK_MID( L, 1); | ||
647 | return 1; | ||
640 | } | 648 | } |
641 | STACK_CHECK( K); | 649 | STACK_CHECK( K); |
642 | 650 | ||
@@ -652,14 +660,26 @@ char const* init_keepers( lua_State* L) | |||
652 | lua_getglobal( L, "package"); // package | 660 | lua_getglobal( L, "package"); // package |
653 | if( !lua_isnil( L, -1)) | 661 | if( !lua_isnil( L, -1)) |
654 | { | 662 | { |
655 | luaG_inter_copy_package( L, K, -1, eLM_ToKeeper); | 663 | // when copying with mode eLM_ToKeeper, error message is pushed at the top of the stack, not raised immediately |
664 | if( luaG_inter_copy_package( L, K, -1, eLM_ToKeeper)) | ||
665 | { | ||
666 | // if something went wrong, the error message is at the top of the stack | ||
667 | lua_remove( L, -2); // error_msg | ||
668 | STACK_MID( L, 1); | ||
669 | return 1; | ||
670 | } | ||
656 | } | 671 | } |
657 | lua_pop( L, 1); // | 672 | lua_pop( L, 1); // |
658 | STACK_MID( L, 0); | 673 | STACK_MID( L, 0); |
659 | 674 | ||
660 | // attempt to call on_state_create(), if we have one and it is a C function | 675 | // attempt to call on_state_create(), if we have one and it is a C function |
661 | // (only support a C function because we can't transfer executable Lua code in keepers) | 676 | // (only support a C function because we can't transfer executable Lua code in keepers) |
662 | call_on_state_create( K, L, eLM_ToKeeper); | 677 | if( call_on_state_create( K, L, eLM_ToKeeper)) |
678 | { | ||
679 | // if something went wrong, the error message is at the top of the stack | ||
680 | STACK_MID( L, 1); // error_msg | ||
681 | return 1; | ||
682 | } | ||
663 | 683 | ||
664 | // to see VM name in Decoda debugger | 684 | // to see VM name in Decoda debugger |
665 | lua_pushliteral( K, "Keeper #"); // "Keeper #" | 685 | lua_pushliteral( K, "Keeper #"); // "Keeper #" |
@@ -678,11 +698,8 @@ char const* init_keepers( lua_State* L) | |||
678 | MUTEX_RECURSIVE_INIT( &GKeepers[i].lock_); | 698 | MUTEX_RECURSIVE_INIT( &GKeepers[i].lock_); |
679 | GKeepers[i].L = K; | 699 | GKeepers[i].L = K; |
680 | } | 700 | } |
681 | #if HAVE_KEEPER_ATEXIT_DESINIT | ||
682 | atexit( atexit_close_keepers); | ||
683 | #endif // HAVE_KEEPER_ATEXIT_DESINIT | ||
684 | STACK_END( L, 0); | 701 | STACK_END( L, 0); |
685 | return NULL; // ok | 702 | return 0; // success |
686 | } | 703 | } |
687 | 704 | ||
688 | struct s_Keeper* keeper_acquire( unsigned long magic_) | 705 | struct s_Keeper* keeper_acquire( unsigned long magic_) |