Created
June 1, 2012 01:28
-
-
Save shirok/2847902 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/ChangeLog b/ChangeLog | |
| index 6b06cc3..344d74f 100644 | |
| --- a/ChangeLog | |
| +++ b/ChangeLog | |
| @@ -1,3 +1,8 @@ | |
| +2012-05-31 Shiro Kawai <shiro@acm.org> | |
| + | |
| + * ext/threads/thread.c (Scm_ThreadTerminate): Fixed SEGV bug when | |
| + thread-terminate! is called on a thread that's not running. | |
| + | |
| 2012-05-28 Shiro Kawai <shiro@acm.org> | |
| * gc/dyn_load.c: Backport a patch for NetBSD 6. | |
| @@ -6,8 +11,8 @@ | |
| 2012-05-27 Shiro Kawai <shiro@acm.org> | |
| - * src/port.c (Scm__SetupPortsForWindows): Protect the origina | |
| - scm_stdout and scm_stderr to be GC-ed, for not having fd 1 and 2 | |
| + * src/port.c (Scm__SetupPortsForWindows): Protect the original | |
| + scm_stdout and scm_stderr from being GC-ed, for not having fd 1 and 2 | |
| open causes problems when spawning child processes and communicate | |
| with them via pipes. Thanks to @natsutan for tracking the problem. | |
| * src/main.c (init_console): make sure fd 0, 1, and 2 are redirected | |
| diff --git a/ext/threads/test.scm b/ext/threads/test.scm | |
| index 9ef7f29..da43cdb 100644 | |
| --- a/ext/threads/test.scm | |
| +++ b/ext/threads/test.scm | |
| @@ -100,6 +100,18 @@ | |
| (thread-terminate! t1) | |
| (thread-join! t1)))) | |
| +;; this SEGVs on 0.9.3.3. test code from @cryks. | |
| +(test* "thread termination before running" 'terminated | |
| + (let1 t1 (make-thread (^[] #f)) | |
| + (thread-terminate! t1) | |
| + (thread-state t1))) | |
| + | |
| +(test* "thread termination while being stopped" 'terminated | |
| + (let1 t1 (thread-start! (make-thread (^[] (let loop () (loop))))) | |
| + (thread-stop! t1) | |
| + (thread-terminate! t1) | |
| + (thread-state t1))) | |
| + | |
| ;;--------------------------------------------------------------------- | |
| (test-section "thread and error") | |
| diff --git a/ext/threads/threads.c b/ext/threads/threads.c | |
| index e60a91e..1ab1aac 100644 | |
| --- a/ext/threads/threads.c | |
| +++ b/ext/threads/threads.c | |
| @@ -432,36 +432,41 @@ ScmObj Scm_ThreadTerminate(ScmVM *target) | |
| } | |
| (void)SCM_INTERNAL_MUTEX_LOCK(target->vmlock); | |
| - do { | |
| - /* This ensures only the first call of thread-terminate! on a thread | |
| - is in effect. */ | |
| - if (target->canceller == NULL) { | |
| - target->canceller = vm; | |
| - | |
| - /* First try */ | |
| - target->stopRequest = SCM_VM_REQUEST_TERMINATE; | |
| - target->attentionRequest = TRUE; | |
| - if (wait_for_termination(target)) break; | |
| - | |
| - /* Second try */ | |
| + if (target->state == SCM_VM_RUNNABLE || target->state == SCM_VM_STOPPED) { | |
| + do { | |
| + /* This ensures only the first call of thread-terminate! on a | |
| + thread is in effect. */ | |
| + if (target->canceller == NULL) { | |
| + target->canceller = vm; | |
| + | |
| + /* First try */ | |
| + target->stopRequest = SCM_VM_REQUEST_TERMINATE; | |
| + target->attentionRequest = TRUE; | |
| + if (wait_for_termination(target)) break; | |
| + | |
| + /* Second try */ | |
| + SCM_ASSERT(target->thread); | |
| #if defined(GAUCHE_USE_PTHREADS) | |
| # if defined(GAUCHE_PTHREAD_SIGNAL) | |
| - pthread_kill(target->thread, GAUCHE_PTHREAD_SIGNAL); | |
| + pthread_kill(target->thread, GAUCHE_PTHREAD_SIGNAL); | |
| # endif /*defined(GAUCHE_PTHREAD_SIGNAL)*/ | |
| #elif defined(GAUCHE_USE_WTHREADS) | |
| - /* TODO: implement signal mechanism using an event */ | |
| + /* TODO: implement signal mechanism using an event */ | |
| #endif /* defined(GAUCHE_USE_WTHREADS) */ | |
| - if (wait_for_termination(target)) break; | |
| + if (wait_for_termination(target)) break; | |
| - /* Last resort */ | |
| - thread_cleanup_inner(target); | |
| + /* Last resort */ | |
| + thread_cleanup_inner(target); | |
| #if defined(GAUCHE_USE_PTHREADS) | |
| - pthread_cancel(target->thread); | |
| + pthread_cancel(target->thread); | |
| #elif defined(GAUCHE_USE_WTHREADS) | |
| - TerminateThread(target->thread, 0); | |
| + TerminateThread(target->thread, 0); | |
| #endif | |
| - } | |
| - } while (0); | |
| + } | |
| + } while (0); | |
| + } | |
| + /* target either is terminated or hasn't been run */ | |
| + target->state = SCM_VM_TERMINATED; | |
| (void)SCM_INTERNAL_MUTEX_UNLOCK(target->vmlock); | |
| return SCM_UNDEFINED; | |
| } | |
| diff --git a/test/control.scm b/test/control.scm | |
| index bd280df..72754b9 100644 | |
| --- a/test/control.scm | |
| +++ b/test/control.scm | |
| @@ -72,7 +72,7 @@ | |
| ;; | |
| (cond-expand | |
| - [gauche.sys.pthreads | |
| + [gauche.sys.threads | |
| (test-section "control.thread-pool") | |
| (use control.thread-pool) | |
| (test-module 'control.thread-pool) | |
| @@ -173,7 +173,15 @@ | |
| (let1 xjob (add-job! pool work) | |
| (terminate-all! pool :force-timeout 0.05) | |
| (job-status xjob)))) | |
| - ] | |
| + | |
| + ;; This SEGVs on 0.9.3.3 (test code by @cryks) | |
| + (test* "thread pool termination" 'terminated | |
| + (let ([t (thread-start! (make-thread (cut undefined)))] | |
| + [pool (make-thread-pool 10)]) | |
| + (terminate-all! pool) | |
| + (thread-terminate! t) | |
| + (thread-state t))) | |
| + ] ; gauche.sys.pthreads | |
| [else]) | |
| (test-end) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment