diff options
author | moteus <mimir@newmail.ru> | 2013-12-27 15:39:38 +0400 |
---|---|---|
committer | moteus <mimir@newmail.ru> | 2013-12-27 15:39:38 +0400 |
commit | a26ecf383900e4c396958da80200cb2eb1121506 (patch) | |
tree | be2909b271537c31e4b3973d89f02696712f2779 | |
parent | bccb6bef9d7eb56eece7efa96524a5fea1eb8d73 (diff) | |
download | lua-llthreads2-a26ecf383900e4c396958da80200cb2eb1121506.tar.gz lua-llthreads2-a26ecf383900e4c396958da80200cb2eb1121506.tar.bz2 lua-llthreads2-a26ecf383900e4c396958da80200cb2eb1121506.zip |
Fix. detach joined thread.
Fix. try use child Lua state in join for detached thread.
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | src/llthread.c | 38 | ||||
-rw-r--r-- | test/test_join_detach.lua | 28 |
3 files changed, 60 insertions, 10 deletions
@@ -13,8 +13,8 @@ This is full dropin replacement for [llthreads](https://github.com/Neopallium/lu | |||
13 | * register loaders for llthreads library itself | 13 | * register loaders for llthreads library itself |
14 | 14 | ||
15 | ##Additional | 15 | ##Additional |
16 | * thread:join() method support zero timeout to check if thread alive | 16 | * thread:join() method support zero timeout to check if thread alive (does not work on Windows with pthreads) |
17 | * thread:join() method support arbitrary timeout on Windows platform | 17 | * thread:join() method support arbitrary timeout on Windows threads |
18 | * set_logger function allow logging errors (crash Lua VM) in current llthread's threads | 18 | * set_logger function allow logging errors (crash Lua VM) in current llthread's threads |
19 | * thread:start() has additional parameter which control in which thread child Lua VM will be destroyed | 19 | * thread:start() has additional parameter which control in which thread child Lua VM will be destroyed |
20 | 20 | ||
diff --git a/src/llthread.c b/src/llthread.c index 53a25b8..668a8c8 100644 --- a/src/llthread.c +++ b/src/llthread.c | |||
@@ -439,14 +439,19 @@ static OS_THREAD_RETURN llthread_child_thread_run(void *arg) { | |||
439 | //{ llthread | 439 | //{ llthread |
440 | 440 | ||
441 | static void llthread_validate(llthread_t *this){ | 441 | static void llthread_validate(llthread_t *this){ |
442 | /* describe valid state of llthread_t object | ||
443 | * from after create and before destroy | ||
444 | */ | ||
442 | if(!FLAGS_IS_SET(this, TSTATE_STARTED)){ | 445 | if(!FLAGS_IS_SET(this, TSTATE_STARTED)){ |
443 | assert(!FLAGS_IS_SET(this, TSTATE_DETACHED)); | 446 | assert(!FLAGS_IS_SET(this, TSTATE_DETACHED)); |
444 | assert(!FLAGS_IS_SET(this, TSTATE_JOINED)); | 447 | assert(!FLAGS_IS_SET(this, TSTATE_JOINED)); |
448 | assert(!FLAGS_IS_SET(this, FLAG_JOIN_LUA)); | ||
449 | return; | ||
445 | } | 450 | } |
446 | else{ | 451 | |
447 | if(FLAGS_IS_SET(this, TSTATE_DETACHED)){ | 452 | if(FLAGS_IS_SET(this, TSTATE_DETACHED)){ |
448 | if(FLAGS_IS_SET(this, FLAG_JOIN_LUA)) assert(this->child == NULL); | 453 | if(!FLAGS_IS_SET(this, FLAG_JOIN_LUA)) assert(this->child == NULL); |
449 | } | 454 | else assert(this->child != NULL); |
450 | } | 455 | } |
451 | } | 456 | } |
452 | 457 | ||
@@ -520,6 +525,10 @@ static int llthread_detach(llthread_t *this){ | |||
520 | 525 | ||
521 | assert(FLAGS_IS_SET(this, TSTATE_STARTED)); | 526 | assert(FLAGS_IS_SET(this, TSTATE_STARTED)); |
522 | 527 | ||
528 | /*we can not deatach joined thread*/ | ||
529 | if(FLAGS_IS_SET(this, TSTATE_JOINED)) | ||
530 | return 0; | ||
531 | |||
523 | this->child = NULL; | 532 | this->child = NULL; |
524 | #ifdef USE_PTHREAD | 533 | #ifdef USE_PTHREAD |
525 | rc = pthread_detach(this->thread); | 534 | rc = pthread_detach(this->thread); |
@@ -545,9 +554,10 @@ static int llthread_start(llthread_t *this, int start_detached, int join_lua) { | |||
545 | llthread_child_t *child = this->child; | 554 | llthread_child_t *child = this->child; |
546 | int rc = 0; | 555 | int rc = 0; |
547 | 556 | ||
548 | if(join_lua){ /*child does not close lua_State*/ | 557 | llthread_validate(this); |
549 | FLAG_SET(child, FLAG_JOIN_LUA); | 558 | |
550 | } | 559 | if(join_lua) FLAG_SET(child, FLAG_JOIN_LUA); |
560 | if(start_detached) FLAG_SET(child, TSTATE_DETACHED); | ||
551 | 561 | ||
552 | #ifndef USE_PTHREAD | 562 | #ifndef USE_PTHREAD |
553 | this->thread = (HANDLE)_beginthreadex(NULL, 0, llthread_child_thread_run, child, 0, NULL); | 563 | this->thread = (HANDLE)_beginthreadex(NULL, 0, llthread_child_thread_run, child, 0, NULL); |
@@ -567,10 +577,14 @@ static int llthread_start(llthread_t *this, int start_detached, int join_lua) { | |||
567 | } | 577 | } |
568 | } | 578 | } |
569 | 579 | ||
580 | llthread_validate(this); | ||
581 | |||
570 | return rc; | 582 | return rc; |
571 | } | 583 | } |
572 | 584 | ||
573 | static int llthread_join(llthread_t *this, join_timeout_t timeout) { | 585 | static int llthread_join(llthread_t *this, join_timeout_t timeout) { |
586 | llthread_validate(this); | ||
587 | |||
574 | if(FLAG_IS_SET(this, TSTATE_JOINED)){ | 588 | if(FLAG_IS_SET(this, TSTATE_JOINED)){ |
575 | return JOIN_OK; | 589 | return JOIN_OK; |
576 | } else{ | 590 | } else{ |
@@ -582,6 +596,9 @@ static int llthread_join(llthread_t *this, join_timeout_t timeout) { | |||
582 | CloseHandle( this->thread ); | 596 | CloseHandle( this->thread ); |
583 | this->thread = INVALID_THREAD; | 597 | this->thread = INVALID_THREAD; |
584 | FLAG_SET(this, TSTATE_JOINED); | 598 | FLAG_SET(this, TSTATE_JOINED); |
599 | |||
600 | llthread_validate(this); | ||
601 | |||
585 | return JOIN_OK; | 602 | return JOIN_OK; |
586 | } | 603 | } |
587 | else if( ret == WAIT_TIMEOUT ){ | 604 | else if( ret == WAIT_TIMEOUT ){ |
@@ -612,6 +629,9 @@ static int llthread_join(llthread_t *this, join_timeout_t timeout) { | |||
612 | FLAG_SET(this, TSTATE_JOINED); | 629 | FLAG_SET(this, TSTATE_JOINED); |
613 | rc = JOIN_OK; | 630 | rc = JOIN_OK; |
614 | } | 631 | } |
632 | |||
633 | llthread_validate(this); | ||
634 | |||
615 | return rc; | 635 | return rc; |
616 | #endif | 636 | #endif |
617 | } | 637 | } |
@@ -641,6 +661,8 @@ static llthread_t *llthread_create(lua_State *L, const char *code, size_t code_l | |||
641 | /* Push all args after the Lua code. */ | 661 | /* Push all args after the Lua code. */ |
642 | llthread_push_args(L, child, 3, lua_gettop(L)); | 662 | llthread_push_args(L, child, 3, lua_gettop(L)); |
643 | 663 | ||
664 | llthread_validate(this); | ||
665 | |||
644 | return this; | 666 | return this; |
645 | } | 667 | } |
646 | 668 | ||
@@ -710,7 +732,7 @@ static int l_llthread_join(lua_State *L) { | |||
710 | if(child && FLAG_IS_SET(this, TSTATE_JOINED)) { | 732 | if(child && FLAG_IS_SET(this, TSTATE_JOINED)) { |
711 | int top; | 733 | int top; |
712 | 734 | ||
713 | if(!FLAG_IS_SET(this, FLAG_JOIN_LUA)){ | 735 | if(FLAG_IS_SET(this, TSTATE_DETACHED) || !FLAG_IS_SET(this, FLAG_JOIN_LUA)){ |
714 | /*child lua state has been destroyed by child thread*/ | 736 | /*child lua state has been destroyed by child thread*/ |
715 | /*@todo return thread exit code*/ | 737 | /*@todo return thread exit code*/ |
716 | lua_pushnumber(L, 0); | 738 | lua_pushnumber(L, 0); |
diff --git a/test/test_join_detach.lua b/test/test_join_detach.lua index dd3ef11..329fb27 100644 --- a/test/test_join_detach.lua +++ b/test/test_join_detach.lua | |||
@@ -22,5 +22,33 @@ end | |||
22 | -- we should not hungup | 22 | -- we should not hungup |
23 | for i = 1, 10 do collectgarbage("collect") end | 23 | for i = 1, 10 do collectgarbage("collect") end |
24 | 24 | ||
25 | |||
26 | do | ||
27 | |||
28 | local thread = llthreads.new(utils.thread_init .. [[ | ||
29 | local sleep = require"utils".sleep | ||
30 | sleep(1) | ||
31 | ]]) | ||
32 | |||
33 | -- detached + joindable | ||
34 | thread:start(true, true) | ||
35 | |||
36 | local ok, err = thread:join(0) | ||
37 | print("thread:join(0): ", ok, err) | ||
38 | assert(ok == nil) | ||
39 | assert(err == "timeout") | ||
40 | |||
41 | utils.sleep(5) | ||
42 | local ok, err = thread:join(0) | ||
43 | print("thread:join(0): ", ok, err) | ||
44 | assert(ok) | ||
45 | |||
46 | end | ||
47 | |||
48 | -- enforce collect `thread` object | ||
49 | -- we should not get av | ||
50 | for i = 1, 10 do collectgarbage("collect") end | ||
51 | |||
52 | |||
25 | print("Done!") | 53 | print("Done!") |
26 | 54 | ||