aboutsummaryrefslogtreecommitdiff
path: root/src/lanes.c
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2011-02-14 21:19:28 +0100
committerBenoit Germain <bnt.germain@gmail.com>2011-02-14 21:19:28 +0100
commitbaeb379c2e4eb436ecb0bcc4d88cb50930ef378e (patch)
tree3f6f0f919305afbe671eee31bcc7ac22bf531f57 /src/lanes.c
parenta661736f7984292a41d71847de68590f6b8ca08a (diff)
downloadlanes-baeb379c2e4eb436ecb0bcc4d88cb50930ef378e.tar.gz
lanes-baeb379c2e4eb436ecb0bcc4d88cb50930ef378e.tar.bz2
lanes-baeb379c2e4eb436ecb0bcc4d88cb50930ef378e.zip
Fixed application hang-up because keeper state was not released in case of errors thrown by inter-state data copy for unsupported types
Diffstat (limited to 'src/lanes.c')
-rw-r--r--src/lanes.c643
1 files changed, 364 insertions, 279 deletions
diff --git a/src/lanes.c b/src/lanes.c
index 16a8edc..f650d9a 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -330,10 +330,12 @@ void serialize_require( lua_State *L ) {
330* bigger the pool, the less chances of unnecessary waits. Lindas map to the 330* bigger the pool, the less chances of unnecessary waits. Lindas map to the
331* keepers randomly, by a hash. 331* keepers randomly, by a hash.
332*/ 332*/
333struct s_Keeper { 333struct s_Keeper
334 MUTEX_T lock_; 334{
335 lua_State *L; 335 MUTEX_T lock_;
336} keeper[ KEEPER_STATES_N ]; 336 lua_State *L;
337 //int count;
338} GKeepers[KEEPER_STATES_N];
337 339
338/* We could use an empty table in 'keeper.lua' as the sentinel, but maybe 340/* We could use an empty table in 'keeper.lua' as the sentinel, but maybe
339* checking for a lightuserdata is faster. 341* checking for a lightuserdata is faster.
@@ -378,30 +380,33 @@ static const char *init_keepers(void) {
378 return err; 380 return err;
379 } 381 }
380 382
381 MUTEX_INIT( &keeper[i].lock_ ); 383 MUTEX_INIT( &GKeepers[i].lock_ );
382 keeper[i].L= L; 384 GKeepers[i].L= L;
385 //GKeepers[i].count = 0;
383 } 386 }
384 return NULL; // ok 387 return NULL; // ok
385} 388}
386 389
387static 390static struct s_Keeper *keeper_acquire( const void *ptr)
388struct s_Keeper *keeper_acquire( const void *ptr ) { 391{
389 /* 392 /*
390 * Any hashing will do that maps pointers to 0..KEEPER_STATES_N-1 393 * Any hashing will do that maps pointers to 0..KEEPER_STATES_N-1
391 * consistently. 394 * consistently.
392 * 395 *
393 * Pointers are often aligned by 8 or so - ignore the low order bits 396 * Pointers are often aligned by 8 or so - ignore the low order bits
394 */ 397 */
395 unsigned int i= ((unsigned long)(ptr) >> 3) % KEEPER_STATES_N; 398 unsigned int i= ((unsigned long)(ptr) >> 3) % KEEPER_STATES_N;
396 struct s_Keeper *K= &keeper[i]; 399 struct s_Keeper *K= &GKeepers[i];
397 400
398 MUTEX_LOCK( &K->lock_ ); 401 MUTEX_LOCK( &K->lock_);
399 return K; 402 //++ K->count;
403 return K;
400} 404}
401 405
402static 406static void keeper_release( struct s_Keeper *K)
403void keeper_release( struct s_Keeper *K ) { 407{
404 MUTEX_UNLOCK( &K->lock_ ); 408 //-- K->count;
409 MUTEX_UNLOCK( &K->lock_);
405} 410}
406 411
407/* 412/*
@@ -411,30 +416,34 @@ void keeper_release( struct s_Keeper *K ) {
411* 'linda': deep Linda pointer (used only as a unique table key, first parameter) 416* 'linda': deep Linda pointer (used only as a unique table key, first parameter)
412* 'starting_index': first of the rest of parameters (none if 0) 417* 'starting_index': first of the rest of parameters (none if 0)
413* 418*
414* Returns: number of return values (pushed to 'L') 419* Returns: number of return values (pushed to 'L') or -1 in case of error
415*/ 420*/
416static 421static int keeper_call( lua_State *K, char const *func_name, lua_State *L, struct s_Linda *linda, uint_t starting_index)
417int keeper_call( lua_State* K, const char *func_name, 422{
418 lua_State *L, struct s_Linda *linda, uint_t starting_index ) { 423 int const args = starting_index ? (lua_gettop(L) - starting_index +1) : 0;
419 424 int const Ktos = lua_gettop(K);
420 int args= starting_index ? (lua_gettop(L) - starting_index +1) : 0; 425 int retvals = -1;
421 int Ktos= lua_gettop(K);
422 int retvals;
423
424 STACK_GROW( K, 2 );
425 426
426 lua_getglobal( K, func_name ); 427 STACK_GROW( K, 2);
427 ASSERT_L( lua_isfunction(K,-1) );
428 428
429 lua_pushlightuserdata( K, linda ); 429 lua_getglobal( K, func_name);
430 ASSERT_L( lua_isfunction(K, -1));
430 431
431 luaG_inter_copy( L,K, args ); // L->K 432 lua_pushlightuserdata( K, linda);
432 lua_call( K, 1+args, LUA_MULTRET );
433 433
434 retvals= lua_gettop(K) - Ktos; 434 if( (args == 0) || luaG_inter_copy( L, K, args) == 0) // L->K
435 {
436 lua_call( K, 1 + args, LUA_MULTRET);
435 437
436 luaG_inter_move( K,L, retvals ); // K->L 438 retvals = lua_gettop( K) - Ktos;
437 return retvals; 439 if( (retvals > 0) && luaG_inter_move( K, L, retvals) != 0) // K->L
440 {
441 retvals = -1;
442 }
443 }
444 // whatever happens, restore the stack to where it was at the origin
445 lua_settop( K, Ktos);
446 return retvals;
438} 447}
439 448
440 449
@@ -463,98 +472,120 @@ static void linda_id( lua_State*, char const * const which);
463* Returns: 'true' if the value was queued 472* Returns: 'true' if the value was queued
464* 'false' for timeout (only happens when the queue size is limited) 473* 'false' for timeout (only happens when the queue size is limited)
465*/ 474*/
466LUAG_FUNC( linda_send ) 475LUAG_FUNC( linda_send)
467{ 476{
468 struct s_Linda *linda= lua_toLinda( L, 1 ); 477 struct s_Linda *linda = lua_toLinda( L, 1);
469 bool_t ret; 478 bool_t ret;
470 bool_t cancel= FALSE; 479 bool_t cancel = FALSE;
471 struct s_Keeper *K; 480 int pushed;
472 time_d timeout= -1.0; 481 time_d timeout= -1.0;
473 uint_t key_i= 2; // index of first key, if timeout not there 482 uint_t key_i = 2; // index of first key, if timeout not there
474
475 luaL_argcheck( L, linda, 1, "expected a linda object!");
476 483
477 if (lua_isnumber(L,2)) { 484 luaL_argcheck( L, linda, 1, "expected a linda object!");
478 timeout= SIGNAL_TIMEOUT_PREPARE( lua_tonumber(L,2) );
479 key_i++;
480 } else if (lua_isnil(L,2))
481 key_i++;
482 485
483 if (lua_isnil(L,key_i)) 486 if( lua_isnumber(L, 2))
484 luaL_error( L, "nil key" ); 487 {
488 timeout= SIGNAL_TIMEOUT_PREPARE( lua_tonumber(L,2) );
489 key_i++;
490 }
491 else if( lua_isnil( L, 2))
492 {
493 key_i++;
494 }
485 495
486 STACK_GROW(L,1); 496 if( lua_isnil( L, key_i))
497 luaL_error( L, "nil key" );
487 498
488 K= keeper_acquire( linda ); 499 STACK_GROW(L, 1);
489 { 500 {
490 lua_State *KL= K->L; // need to do this for 'STACK_CHECK' 501 struct s_Keeper *K = keeper_acquire( linda);
491STACK_CHECK(KL) 502 lua_State *KL = K->L; // need to do this for 'STACK_CHECK'
492 while(TRUE) { 503 STACK_CHECK( KL)
493 int pushed; 504 for( ;;)
494 505 {
495STACK_MID(KL,0) 506 STACK_MID(KL, 0)
496 pushed= keeper_call( K->L, "send", L, linda, key_i ); 507 pushed = keeper_call( KL, "send", L, linda, key_i);
497 ASSERT_L( pushed==1 ); 508 if( pushed < 0)
498 509 {
499 ret= lua_toboolean(L,-1); 510 break;
500 lua_pop(L,1); 511 }
501 512 ASSERT_L( pushed == 1);
502 if (ret) { 513
503 // Wake up ALL waiting threads 514 ret = lua_toboolean( L, -1);
504 // 515 lua_pop( L, 1);
505 SIGNAL_ALL( &linda->write_happened ); 516
506 break; 517 if( ret)
507 518 {
508 } else if (timeout==0.0) { 519 // Wake up ALL waiting threads
509 break; /* no wait; instant timeout */ 520 //
510 521 SIGNAL_ALL( &linda->write_happened);
511 } else { 522 break;
512 /* limit faced; push until timeout */ 523
513 524 }
514 cancel= cancel_test( L ); // testing here causes no delays 525 if( timeout == 0.0)
515 if (cancel) break; 526 {
516 527 break; /* no wait; instant timeout */
517// Bugfix by Benoit Germain Dec-2009: change status of lane to "waiting" 528 }
518// 529 /* limit faced; push until timeout */
530
531 cancel = cancel_test( L); // testing here causes no delays
532 if (cancel)
533 break;
534
535 // Bugfix by Benoit Germain Dec-2009: change status of lane to "waiting"
536 //
519#if 1 537#if 1
520{ 538 {
521 struct s_lane *s; 539 struct s_lane *s;
522 enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings 540 enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings
523 STACK_GROW(L,1); 541 STACK_GROW(L, 1);
524 542
525 STACK_CHECK(L) 543 STACK_CHECK(L)
526 lua_pushlightuserdata( L, CANCEL_TEST_KEY ); 544 lua_pushlightuserdata( L, CANCEL_TEST_KEY);
527 lua_rawget( L, LUA_REGISTRYINDEX ); 545 lua_rawget( L, LUA_REGISTRYINDEX);
528 s= lua_touserdata( L, -1 ); // lightuserdata (true 's_lane' pointer) / nil 546 s = lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) / nil
529 lua_pop(L,1); 547 lua_pop(L, 1);
530 STACK_END(L,0) 548 STACK_END(L,0)
531 if (s) { 549 if( s)
532 prev_status = s->status; 550 {
533 s->status = WAITING; 551 prev_status = s->status;
534 } 552 s->status = WAITING;
535 if (!SIGNAL_WAIT( &linda->read_happened, &K->lock_, timeout )) { 553 }
536 if (s) { s->status = prev_status; } 554 if( !SIGNAL_WAIT( &linda->read_happened, &K->lock_, timeout))
537 break; 555 {
538 } 556 if( s)
539 if (s) s->status = prev_status; 557 {
540} 558 s->status = prev_status;
559 }
560 break;
561 }
562 if( s)
563 {
564 s->status = prev_status;
565 }
566 }
541#else 567#else
542 // K lock will be released for the duration of wait and re-acquired 568 // K lock will be released for the duration of wait and re-acquired
543 // 569 //
544 if (!SIGNAL_WAIT( &linda->read_happened, &K->lock_, timeout )) 570 if( !SIGNAL_WAIT( &linda->read_happened, &K->lock_, timeout))
545 break; // timeout 571 break; // timeout
546#endif 572#endif
547 } 573 }
548 } 574 STACK_END( KL, 0)
549STACK_END(KL,0) 575 keeper_release( K);
550 } 576 }
551 keeper_release(K);
552 577
553 if (cancel) 578 // must trigger error after keeper state has been released
554 cancel_error(L); 579 if( pushed < 0)
555 580 {
556 lua_pushboolean( L, ret ); 581 luaL_error( L, "tried to copy unsupported types");
557 return 1; 582 }
583
584 if( cancel)
585 cancel_error( L);
586
587 lua_pushboolean( L, ret);
588 return 1;
558} 589}
559 590
560 591
@@ -566,81 +597,110 @@ STACK_END(KL,0)
566* Returns: value received (which is consumed from the slot) 597* Returns: value received (which is consumed from the slot)
567* key which had it 598* key which had it
568*/ 599*/
569LUAG_FUNC( linda_receive ) { 600LUAG_FUNC( linda_receive)
570 struct s_Linda *linda= lua_toLinda( L, 1 ); 601{
571 int pushed; 602 struct s_Linda *linda = lua_toLinda( L, 1);
572 bool_t cancel= FALSE; 603 int pushed;
573 struct s_Keeper *K; 604 bool_t cancel = FALSE;
574 time_d timeout= -1.0; 605
575 uint_t key_i= 2; 606 time_d timeout = -1.0;
576 607 uint_t key_i = 2;
577 luaL_argcheck( L, linda, 1, "expected a linda object!");
578
579 if (lua_isnumber(L,2)) {
580 timeout= SIGNAL_TIMEOUT_PREPARE( lua_tonumber(L,2) );
581 key_i++;
582 } else if (lua_isnil(L,2))
583 key_i++;
584
585 K= keeper_acquire( linda );
586 {
587 while(TRUE) {
588 pushed= keeper_call( K->L, "receive", L, linda, key_i );
589 if (pushed) {
590 ASSERT_L( pushed==2 );
591
592 // To be done from within the 'K' locking area
593 //
594 SIGNAL_ALL( &linda->read_happened );
595 break;
596 608
597 } else if (timeout==0.0) { 609 luaL_argcheck( L, linda, 1, "expected a linda object!");
598 break; /* instant timeout */
599 610
600 } else { /* nothing received; wait until timeout */ 611 if( lua_isnumber( L, 2))
601 612 {
602 cancel= cancel_test( L ); // testing here causes no delays 613 timeout = SIGNAL_TIMEOUT_PREPARE( lua_tonumber( L, 2));
603 if (cancel) break; 614 key_i++;
615 }
616 else if( lua_isnil( L, 2))
617 {
618 key_i++;
619 }
604 620
605// Bugfix by Benoit Germain Dec-2009: change status of lane to "waiting" 621 {
606// 622 struct s_Keeper *K = keeper_acquire( linda);
623 for( ;;)
624 {
625 pushed = keeper_call( K->L, "receive", L, linda, key_i);
626 if( pushed < 0)
627 {
628 break;
629 }
630 if( pushed > 0)
631 {
632 ASSERT_L( pushed == 2);
633
634 // To be done from within the 'K' locking area
635 //
636 SIGNAL_ALL( &linda->read_happened);
637 break;
638
639 }
640 if( timeout == 0.0)
641 {
642 break; /* instant timeout */
643 }
644 /* nothing received; wait until timeout */
645
646 cancel = cancel_test( L); // testing here causes no delays
647 if( cancel)
648 {
649 break;
650 }
651
652 // Bugfix by Benoit Germain Dec-2009: change status of lane to "waiting"
653 //
607#if 1 654#if 1
608{ 655 {
609 struct s_lane *s; 656 struct s_lane *s;
610 enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings 657 enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings
611 STACK_GROW(L,1); 658 STACK_GROW(L,1);
612 659
613 STACK_CHECK(L) 660 STACK_CHECK(L)
614 lua_pushlightuserdata( L, CANCEL_TEST_KEY ); 661 lua_pushlightuserdata( L, CANCEL_TEST_KEY);
615 lua_rawget( L, LUA_REGISTRYINDEX ); 662 lua_rawget( L, LUA_REGISTRYINDEX);
616 s= lua_touserdata( L, -1 ); // lightuserdata (true 's_lane' pointer) / nil 663 s= lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) / nil
617 lua_pop(L,1); 664 lua_pop(L, 1);
618 STACK_END(L,0) 665 STACK_END(L, 0)
619 if (s) { 666 if( s)
620 prev_status = s->status; 667 {
621 s->status = WAITING; 668 prev_status = s->status;
622 } 669 s->status = WAITING;
623 if (!SIGNAL_WAIT( &linda->write_happened, &K->lock_, timeout )) { 670 }
624 if (s) { s->status = prev_status; } 671 if( !SIGNAL_WAIT( &linda->write_happened, &K->lock_, timeout))
625 break; 672 {
626 } 673 if( s)
627 if (s) s->status = prev_status; 674 {
628} 675 s->status = prev_status;
676 }
677 break;
678 }
679 if( s)
680 {
681 s->status = prev_status;
682 }
683 }
629#else 684#else
630 // Release the K lock for the duration of wait, and re-acquire 685 // Release the K lock for the duration of wait, and re-acquire
631 // 686 //
632 if (!SIGNAL_WAIT( &linda->write_happened, &K->lock_, timeout )) 687 if( !SIGNAL_WAIT( &linda->write_happened, &K->lock_, timeout))
633 break; 688 break;
634#endif 689#endif
635 } 690 }
636 } 691 keeper_release( K);
637 } 692 }
638 keeper_release(K);
639 693
640 if (cancel) 694 // must trigger error after keeper state has been released
641 cancel_error(L); 695 if( pushed < 0)
696 {
697 luaL_error( L, "tried to copy unsupported types");
698 }
642 699
643 return pushed; 700 if( cancel)
701 cancel_error( L);
702
703 return pushed;
644} 704}
645 705
646 706
@@ -651,27 +711,35 @@ LUAG_FUNC( linda_receive ) {
651* 711*
652* Existing slot value is replaced, and possible queue entries removed. 712* Existing slot value is replaced, and possible queue entries removed.
653*/ 713*/
654LUAG_FUNC( linda_set ) { 714LUAG_FUNC( linda_set)
655 struct s_Linda *linda= lua_toLinda( L, 1 ); 715{
656 bool_t has_value= !lua_isnil(L,3); 716 struct s_Linda *linda = lua_toLinda( L, 1);
657 struct s_Keeper *K; 717 bool_t has_value = !lua_isnil( L, 3);
658 718 luaL_argcheck( L, linda, 1, "expected a linda object!");
659 luaL_argcheck( L, linda, 1, "expected a linda object!");
660
661 K= keeper_acquire( linda );
662 {
663 int pushed= keeper_call( K->L, "set", L, linda, 2 );
664 ASSERT_L( pushed==0 );
665 719
666 /* Set the signal from within 'K' locking. 720 {
667 */ 721 struct s_Keeper *K = keeper_acquire( linda);
668 if (has_value) { 722 int pushed = keeper_call( K->L, "set", L, linda, 2);
669 SIGNAL_ALL( &linda->write_happened ); 723 if( pushed >= 0) // no error?
670 } 724 {
671 } 725 ASSERT_L( pushed == 0);
672 keeper_release(K); 726
727 /* Set the signal from within 'K' locking.
728 */
729 if( has_value)
730 {
731 SIGNAL_ALL( &linda->write_happened);
732 }
733 }
734 keeper_release( K);
735 // must trigger error after keeper state has been released
736 if( pushed < 0)
737 {
738 luaL_error( L, "tried to copy unsupported types");
739 }
740 }
673 741
674 return 0; 742 return 0;
675} 743}
676 744
677 745
@@ -680,21 +748,25 @@ LUAG_FUNC( linda_set ) {
680* 748*
681* Get a value from Linda. 749* Get a value from Linda.
682*/ 750*/
683LUAG_FUNC( linda_get ) { 751LUAG_FUNC( linda_get)
684 struct s_Linda *linda= lua_toLinda( L, 1 ); 752{
685 int pushed; 753 struct s_Linda *linda= lua_toLinda( L, 1);
686 struct s_Keeper *K; 754 int pushed;
687 755 luaL_argcheck( L, linda, 1, "expected a linda object!");
688 luaL_argcheck( L, linda, 1, "expected a linda object!");
689 756
690 K= keeper_acquire( linda ); 757 {
691 { 758 struct s_Keeper *K = keeper_acquire( linda);
692 pushed= keeper_call( K->L, "get", L, linda, 2 ); 759 pushed = keeper_call( K->L, "get", L, linda, 2);
693 ASSERT_L( pushed==0 || pushed==1 ); 760 ASSERT_L( pushed==0 || pushed==1 );
694 } 761 keeper_release(K);
695 keeper_release(K); 762 // must trigger error after keeper state has been released
763 if( pushed < 0)
764 {
765 luaL_error( L, "tried to copy unsupported types");
766 }
767 }
696 768
697 return pushed; 769 return pushed;
698} 770}
699 771
700 772
@@ -703,20 +775,24 @@ LUAG_FUNC( linda_get ) {
703* 775*
704* Set limits to 1 or more Linda keys. 776* Set limits to 1 or more Linda keys.
705*/ 777*/
706LUAG_FUNC( linda_limit ) { 778LUAG_FUNC( linda_limit)
707 struct s_Linda *linda= lua_toLinda( L, 1 ); 779{
708 struct s_Keeper *K; 780 struct s_Linda *linda= lua_toLinda( L, 1 );
709 781 luaL_argcheck( L, linda, 1, "expected a linda object!");
710 luaL_argcheck( L, linda, 1, "expected a linda object!");
711 782
712 K= keeper_acquire( linda ); 783 {
713 { 784 struct s_Keeper *K = keeper_acquire( linda);
714 int pushed= keeper_call( K->L, "limit", L, linda, 2 ); 785 int pushed = keeper_call( K->L, "limit", L, linda, 2);
715 ASSERT_L( pushed==0 ); 786 ASSERT_L( pushed <= 0); // either error or no return values
716 } 787 keeper_release( K);
717 keeper_release(K); 788 // must trigger error after keeper state has been released
789 if( pushed < 0)
790 {
791 luaL_error( L, "tried to copy unsupported types");
792 }
793 }
718 794
719 return 0; 795 return 0;
720} 796}
721 797
722 798
@@ -842,7 +918,7 @@ static void linda_id( lua_State *L, char const * const which)
842 918
843LUAG_FUNC( linda) 919LUAG_FUNC( linda)
844{ 920{
845 return luaG_deep_userdata( L, linda_id); 921 return luaG_deep_userdata( L, linda_id);
846} 922}
847 923
848 924
@@ -1111,8 +1187,9 @@ static void selfdestruct_atexit( void ) {
1111 { 1187 {
1112 int i; 1188 int i;
1113 for(i=0;i<KEEPER_STATES_N;i++){ 1189 for(i=0;i<KEEPER_STATES_N;i++){
1114 lua_close(keeper[i].L); 1190 lua_close( GKeepers[i].L);
1115 keeper[i].L = 0; 1191 GKeepers[i].L = 0;
1192 //assert( GKeepers[i].count == 0);
1116 } 1193 }
1117 } 1194 }
1118} 1195}
@@ -1476,7 +1553,7 @@ LUAG_FUNC( thread_new )
1476 lua_gettable( L, -2); 1553 lua_gettable( L, -2);
1477 threadName = lua_tostring( L, -1); 1554 threadName = lua_tostring( L, -1);
1478 lua_pop( L, 1); 1555 lua_pop( L, 1);
1479 luaG_inter_move( L,L2, 1 ); // moves the table to L2 1556 luaG_inter_move( L, L2, 1); // moves the table to L2
1480 1557
1481 // L2 [-1]: table of globals 1558 // L2 [-1]: table of globals
1482 1559
@@ -1500,10 +1577,11 @@ LUAG_FUNC( thread_new )
1500 // Lane main function 1577 // Lane main function
1501 // 1578 //
1502 STACK_CHECK(L) 1579 STACK_CHECK(L)
1503 if( lua_type(L, 1) == LUA_TFUNCTION) 1580 if( lua_type( L, 1) == LUA_TFUNCTION)
1504 { 1581 {
1505 lua_pushvalue( L, 1 ); 1582 lua_pushvalue( L, 1);
1506 luaG_inter_move( L,L2, 1 ); // L->L2 1583 if( luaG_inter_move( L, L2, 1) != 0) // L->L2
1584 luaL_error( L, "tried to copy unsupported types");
1507 STACK_MID(L,0) 1585 STACK_MID(L,0)
1508 } 1586 }
1509 else if( lua_type(L, 1) == LUA_TSTRING) 1587 else if( lua_type(L, 1) == LUA_TSTRING)
@@ -1515,12 +1593,13 @@ LUAG_FUNC( thread_new )
1515 } 1593 }
1516 } 1594 }
1517 1595
1518 ASSERT_L( lua_gettop(L2) == 1 ); 1596 ASSERT_L( lua_gettop(L2) == 1);
1519 ASSERT_L( lua_isfunction(L2,1) ); 1597 ASSERT_L( lua_isfunction(L2,1));
1520 1598
1521 // revive arguments 1599 // revive arguments
1522 // 1600 //
1523 if (args) luaG_inter_copy( L,L2, args ); // L->L2 1601 if( (args > 0) && (luaG_inter_copy( L, L2, args) != 0)) // L->L2
1602 luaL_error( L, "tried to copy unsupported types");
1524 STACK_MID(L,0) 1603 STACK_MID(L,0)
1525 1604
1526 ASSERT_L( (uint_t)lua_gettop(L2) == 1+args ); 1605 ASSERT_L( (uint_t)lua_gettop(L2) == 1+args );
@@ -1756,49 +1835,55 @@ LUAG_FUNC( thread_status )
1756// 1835//
1757LUAG_FUNC( thread_join ) 1836LUAG_FUNC( thread_join )
1758{ 1837{
1759 struct s_lane *s= lua_toLane(L,1); 1838 struct s_lane *s= lua_toLane(L,1);
1760 double wait_secs= luaL_optnumber(L,2,-1.0); 1839 double wait_secs= luaL_optnumber(L,2,-1.0);
1761 lua_State *L2= s->L; 1840 lua_State *L2= s->L;
1762 int ret; 1841 int ret;
1842 bool_t done;
1763 1843
1764 bool_t done= 1844 done = (s->thread == 0) ||
1765#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) 1845#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN)
1766 THREAD_WAIT( &s->thread, wait_secs ); 1846 THREAD_WAIT( &s->thread, wait_secs );
1767#else 1847#else
1768 THREAD_WAIT( &s->thread, &s->done_signal_, &s->done_lock_, &s->status, wait_secs ); 1848 THREAD_WAIT( &s->thread, &s->done_signal_, &s->done_lock_, &s->status, wait_secs);
1769#endif 1849#endif
1770 if (!done) 1850 if (!done || !L2)
1771 return 0; // timeout: pushes none, leaves 'L2' alive 1851 return 0; // timeout: pushes none, leaves 'L2' alive
1772 1852
1773 // Thread is DONE/ERROR_ST/CANCELLED; all ours now 1853 // Thread is DONE/ERROR_ST/CANCELLED; all ours now
1774 1854
1775 STACK_GROW( L, 1 ); 1855 STACK_GROW( L, 1);
1776 1856
1777 switch( s->status ) { 1857 switch( s->status)
1778 case DONE: { 1858 {
1779 uint_t n= lua_gettop(L2); // whole L2 stack 1859 case DONE:
1780 luaG_inter_move( L2,L, n ); 1860 {
1781 ret= n; 1861 uint_t n = lua_gettop( L2); // whole L2 stack
1782 } break; 1862 if( (n > 0) && (luaG_inter_move( L2, L, n) != 0))
1783 1863 luaL_error( L, "tried to copy unsupported types");
1784 case ERROR_ST: 1864 ret = n;
1785 lua_pushnil(L); 1865 }
1786 luaG_inter_move( L2,L, 2 ); // error message at [-2], stack trace at [-1] 1866 break;
1787 ret= 3; 1867
1788 break; 1868 case ERROR_ST:
1789 1869 lua_pushnil( L);
1790 case CANCELLED: 1870 if( luaG_inter_move( L2, L, 2) != 0) // error message at [-2], stack trace at [-1]
1791 ret= 0; 1871 luaL_error( L, "tried to copy unsupported types");
1792 break; 1872 ret= 3;
1793 1873 break;
1794 default: 1874
1795 DEBUGEXEC(fprintf( stderr, "Status: %d\n", s->status )); 1875 case CANCELLED:
1796 ASSERT_L( FALSE ); ret= 0; 1876 ret= 0;
1797 } 1877 break;
1798 lua_close(L2); 1878
1799 s->L = L2 = 0; 1879 default:
1880 DEBUGEXEC(fprintf( stderr, "Status: %d\n", s->status));
1881 ASSERT_L( FALSE ); ret= 0;
1882 }
1883 lua_close( L2);
1884 s->L = L2 = 0;
1800 1885
1801 return ret; 1886 return ret;
1802} 1887}
1803 1888
1804 1889