* Trouble joining with threads from C @ 2011-03-07 5:56 Mark H Weaver 2011-03-09 6:48 ` Mark H Weaver 0 siblings, 1 reply; 12+ messages in thread From: Mark H Weaver @ 2011-03-07 5:56 UTC (permalink / raw) To: guile-devel [-- Attachment #1: Type: text/plain, Size: 444 bytes --] Apologies in advance if I'm making a mistake here, but can someone explain to me why the minimal attached example code fails to join with its trivial spawned thread? I might guess that it's because spawn_thread() in threads.c calls scm_i_pthread_detach. So does launch_thread(). Yet the documentation of scm_join_thread seems to indicate that you ought to be able to join with a thread created by scm_spawn_thread. Thanks, Mark [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: Minimal example code --] [-- Type: text/x-csrc, Size: 481 bytes --] #include <libguile.h> static SCM thread_main (void *data) { return SCM_BOOL_F; } static SCM thread_handler (void *data, SCM key, SCM args) { return SCM_BOOL_F; } static void * inner_main (void *data) { SCM thread = scm_spawn_thread (thread_main, 0, thread_handler, 0); SCM timeout = scm_from_unsigned_integer (time (NULL) + 20); scm_join_thread_timed (thread, timeout, SCM_BOOL_T); } int main (int argc, char **argv) { scm_with_guile (inner_main, 0); return 0; } ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Trouble joining with threads from C 2011-03-07 5:56 Trouble joining with threads from C Mark H Weaver @ 2011-03-09 6:48 ` Mark H Weaver 2011-03-18 12:23 ` Andy Wingo 0 siblings, 1 reply; 12+ messages in thread From: Mark H Weaver @ 2011-03-09 6:48 UTC (permalink / raw) To: guile-devel [-- Attachment #1: Type: text/plain, Size: 961 bytes --] Having further investigated, I'm convinced that this is a bug. Attached are two minimal C programs. Both create threads that do nothing but sleep for 2 seconds and then exit. The parent tries to join with the child thread, with a timeout of 10 seconds. The only difference is that test1 uses scm_spawn_thread, and test2 uses scm_call_with_new_thread. test1 always times out, and test2 works properly. Having looked at the code in threads.c, I'm surprised that either of them work. Both scm_spawn_thread and scm_call_with_new_thread arrange for pthread_detach to be called in the child (in spawn_thread and launch_thread, respectively). This is supposed to make the child un-joinable. I've attached not only test1.c and test2.c, but also the diff between them. I compiled them as follows: gcc -o test1 test1.c $(pkg-config --cflags --libs guile-2.0) gcc -o test2 test2.c $(pkg-config --cflags --libs guile-2.0) Any ideas? Thanks, Mark [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: test1.c, which uses scm_spawn_thread --] [-- Type: text/x-csrc, Size: 920 bytes --] #include <libguile.h> static SCM thread_main (void *data) { /* scm_sleep (scm_from_signed_integer (20)); /* This should cause a timeout */ /* scm_sleep (SCM_BOOL_T); /* This should throw an exception */ scm_sleep (scm_from_signed_integer (2)); /* This should finish */ return scm_from_latin1_string ("finished"); } static SCM thread_handler (void *data, SCM key, SCM args) { return scm_from_latin1_string ("exception thrown"); } static void * inner_main (void *data) { SCM thread = scm_spawn_thread (thread_main, 0, thread_handler, 0); SCM timeout = scm_sum (scm_current_time(), scm_from_signed_integer (10)); SCM result = scm_join_thread_timed (thread, timeout, scm_from_latin1_string ("timed out")); scm_simple_format (SCM_BOOL_T, scm_from_latin1_string ("~A\n"), scm_list_1 (result)); } int main (int argc, char **argv) { scm_with_guile (inner_main, 0); return 0; } [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #3: test2.c, which uses scm_call_with_new_thread --] [-- Type: text/x-csrc, Size: 1098 bytes --] #include <libguile.h> static SCM thread_main (void) { /* scm_sleep (scm_from_signed_integer (20)); /* This should cause a timeout */ /* scm_sleep (SCM_BOOL_T); /* This should throw an exception */ scm_sleep (scm_from_signed_integer (2)); /* This should finish */ return scm_from_latin1_string ("finished"); } static SCM thread_handler (SCM handler, SCM key, SCM args) { return scm_from_latin1_string ("exception thrown"); } static void * inner_main (void *data) { SCM thread_main_proc = scm_c_make_gsubr ("thread-main", 0, 0, 0, thread_main); SCM thread_handler_proc = scm_c_make_gsubr ("thread-handler", 2, 0, 1, thread_handler); SCM thread = scm_call_with_new_thread (thread_main_proc, thread_handler_proc); SCM timeout = scm_sum (scm_current_time(), scm_from_signed_integer (10)); SCM result = scm_join_thread_timed (thread, timeout, scm_from_latin1_string ("timed out")); scm_simple_format (SCM_BOOL_T, scm_from_latin1_string ("~A\n"), scm_list_1 (result)); } int main (int argc, char **argv) { scm_with_guile (inner_main, 0); return 0; } [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #4: Diff between test1.c and test2.c --] [-- Type: text/x-diff, Size: 1207 bytes --] --- test1.c 2011-03-09 01:33:36.000000000 -0500 +++ test2.c 2011-03-09 01:34:18.000000000 -0500 @@ -1,7 +1,7 @@ #include <libguile.h> static SCM -thread_main (void *data) +thread_main (void) { /* scm_sleep (scm_from_signed_integer (20)); /* This should cause a timeout */ /* scm_sleep (SCM_BOOL_T); /* This should throw an exception */ @@ -10,7 +10,7 @@ } static SCM -thread_handler (void *data, SCM key, SCM args) +thread_handler (SCM handler, SCM key, SCM args) { return scm_from_latin1_string ("exception thrown"); } @@ -18,7 +18,9 @@ static void * inner_main (void *data) { + SCM thread_main_proc = scm_c_make_gsubr ("thread-main", 0, 0, 0, thread_main); + SCM thread_handler_proc = scm_c_make_gsubr ("thread-handler", 2, 0, 1, thread_handler); - SCM thread = scm_spawn_thread (thread_main, 0, thread_handler, 0); + SCM thread = scm_call_with_new_thread (thread_main_proc, thread_handler_proc); SCM timeout = scm_sum (scm_current_time(), scm_from_signed_integer (10)); SCM result = scm_join_thread_timed (thread, timeout, scm_from_latin1_string ("timed out")); scm_simple_format (SCM_BOOL_T, scm_from_latin1_string ("~A\n"), scm_list_1 (result)); ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Trouble joining with threads from C 2011-03-09 6:48 ` Mark H Weaver @ 2011-03-18 12:23 ` Andy Wingo 2011-03-20 23:11 ` Ludovic Courtès 0 siblings, 1 reply; 12+ messages in thread From: Andy Wingo @ 2011-03-18 12:23 UTC (permalink / raw) To: Mark H Weaver; +Cc: guile-devel [-- Attachment #1: Type: text/plain, Size: 1291 bytes --] Hi Mark, On Wed 09 Mar 2011 07:48, Mark H Weaver <mhw@netris.org> writes: > Attached are two minimal C programs. Both create threads that do > nothing but sleep for 2 seconds and then exit. The parent tries to join > with the child thread, with a timeout of 10 seconds. > > The only difference is that test1 uses scm_spawn_thread, and test2 uses > scm_call_with_new_thread. test1 always times out, and test2 works > properly. Indeed, a bug. > Having looked at the code in threads.c, I'm surprised that either of > them work. Both scm_spawn_thread and scm_call_with_new_thread arrange > for pthread_detach to be called in the child (in spawn_thread and > launch_thread, respectively). This is supposed to make the child > un-joinable. scm_join_thread_timed doesn't use pthread_join. I don't recall exactly why, but its implementation does look OK, at least at first glance. No, the issue is elsewhere, that the thread-exit handlers were not being called, which makes me trust our pthreads support much less than before, if this bug could exist for so long. I have fixed this in Git with the attached patch, which fixes your test as well. Would you mind submitting (and committing :) a test case? Adding it to test-suite/standalone is probably the thing to do. Regards, Andy [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-fix-thread-cleanup.patch --] [-- Type: text/x-patch, Size: 6719 bytes --] From 4732679c36305b886cbb6bd3473154731535cb0b Mon Sep 17 00:00:00 2001 From: Andy Wingo <wingo@pobox.com> Date: Fri, 18 Mar 2011 13:18:47 +0100 Subject: [PATCH] fix thread cleanup * libguile/threads.h: Always declare a scm_i_thread_key, for cleanup purposes, in the BUILDING_LIBGUILE case. * libguile/threads.c (scm_i_thread_key): Init with a cleanup handler, so any guile-specific info for a thread can be cleaned up reliably. (guilify_self_1): Always set the thread key. (do_thread_exit_trampoline, on_thread_exit): Enter guile-mode for the guile-mode cleanup handler, and trampoline through a gc_call_with_stack_base for reasons explained in the code. (init_thread_key, scm_i_init_thread_for_guile): Always init the key. (scm_i_with_guile_and_parent): No need for pthread_cancel cleanup handlers, as the pthread key destructor will take care of that for us. (really_launch): Remove needless pthread_exit call with incorrect comment. --- libguile/threads.c | 71 ++++++++++++++++++++++++++++----------------------- libguile/threads.h | 5 +++- 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/libguile/threads.c b/libguile/threads.c index e7347ad..e2e17ac 100644 --- a/libguile/threads.c +++ b/libguile/threads.c @@ -343,6 +343,12 @@ unblock_from_queue (SCM queue) /* Getting into and out of guile mode. */ +/* Key used to attach a cleanup handler to a given thread. Also, if + thread-local storage is unavailable, this key is used to retrieve the + current thread with `pthread_getspecific ()'. */ +scm_i_pthread_key_t scm_i_thread_key; + + #ifdef SCM_HAVE_THREAD_STORAGE_CLASS /* When thread-local storage (TLS) is available, a pointer to the @@ -352,17 +358,7 @@ unblock_from_queue (SCM queue) represent. */ SCM_THREAD_LOCAL scm_i_thread *scm_i_current_thread = NULL; -# define SET_CURRENT_THREAD(_t) scm_i_current_thread = (_t) - -#else /* !SCM_HAVE_THREAD_STORAGE_CLASS */ - -/* Key used to retrieve the current thread with `pthread_getspecific ()'. */ -scm_i_pthread_key_t scm_i_thread_key; - -# define SET_CURRENT_THREAD(_t) \ - scm_i_pthread_setspecific (scm_i_thread_key, (_t)) - -#endif /* !SCM_HAVE_THREAD_STORAGE_CLASS */ +#endif /* SCM_HAVE_THREAD_STORAGE_CLASS */ static scm_i_pthread_mutex_t thread_admin_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER; @@ -428,7 +424,12 @@ guilify_self_1 (SCM_STACKITEM *base) t->exited = 0; t->guile_mode = 0; - SET_CURRENT_THREAD (t); + scm_i_pthread_setspecific (scm_i_thread_key, t); + +#ifdef SCM_HAVE_THREAD_STORAGE_CLASS + /* Cache the current thread in TLS for faster lookup. */ + scm_i_current_thread = t; +#endif scm_i_pthread_mutex_lock (&thread_admin_mutex); t->next_thread = all_threads; @@ -537,6 +538,22 @@ do_thread_exit (void *v) return NULL; } +static void * +do_thread_exit_trampoline (struct GC_stack_base *sb, void *v) +{ + void *ret; + int registered; + + registered = GC_register_my_thread (sb); + + ret = scm_with_guile (do_thread_exit, v); + + if (registered == GC_SUCCESS) + GC_unregister_my_thread (); + + return ret; +} + static void on_thread_exit (void *v) { @@ -551,19 +568,20 @@ on_thread_exit (void *v) t->held_mutex = NULL; } - SET_CURRENT_THREAD (v); + /* Reinstate the current thread for purposes of scm_with_guile + guile-mode cleanup handlers. Only really needed in the non-TLS + case but it doesn't hurt to be consistent. */ + scm_i_pthread_setspecific (scm_i_thread_key, t); /* Ensure the signal handling thread has been launched, because we might be shutting it down. */ scm_i_ensure_signal_delivery_thread (); /* Unblocking the joining threads needs to happen in guile mode - since the queue is a SCM data structure. */ - - /* Note: Since `do_thread_exit ()' uses allocates memory via `libgc', we - assume the GC is usable at this point, and notably that thread-local - storage (TLS) hasn't been deallocated yet. */ - do_thread_exit (v); + since the queue is a SCM data structure. Trampoline through + GC_call_with_stack_base so that the GC works even if it already + cleaned up for this thread. */ + GC_call_with_stack_base (do_thread_exit_trampoline, v); /* Removing ourself from the list of all threads needs to happen in non-guile mode since all SCM values on our stack become @@ -590,21 +608,17 @@ on_thread_exit (void *v) scm_i_pthread_mutex_unlock (&thread_admin_mutex); - SET_CURRENT_THREAD (NULL); + scm_i_pthread_setspecific (scm_i_thread_key, NULL); } -#ifndef SCM_HAVE_THREAD_STORAGE_CLASS - static scm_i_pthread_once_t init_thread_key_once = SCM_I_PTHREAD_ONCE_INIT; static void init_thread_key (void) { - scm_i_pthread_key_create (&scm_i_thread_key, NULL); + scm_i_pthread_key_create (&scm_i_thread_key, on_thread_exit); } -#endif - /* Perform any initializations necessary to make the current thread known to Guile (via SCM_I_CURRENT_THREAD), initializing Guile itself, if necessary. @@ -625,9 +639,7 @@ init_thread_key (void) static int scm_i_init_thread_for_guile (SCM_STACKITEM *base, SCM parent) { -#ifndef SCM_HAVE_THREAD_STORAGE_CLASS scm_i_pthread_once (&init_thread_key_once, init_thread_key); -#endif if (SCM_I_CURRENT_THREAD) { @@ -790,9 +802,7 @@ scm_i_with_guile_and_parent (void *(*func)(void *), void *data, SCM parent) /* We are in Guile mode. */ assert (t->guile_mode); - scm_i_pthread_cleanup_push (scm_leave_guile_cleanup, NULL); res = scm_c_with_continuation_barrier (func, data); - scm_i_pthread_cleanup_pop (0); /* Leave Guile mode. */ t->guile_mode = 0; @@ -880,9 +890,6 @@ really_launch (void *d) else t->result = scm_catch (SCM_BOOL_T, thunk, handler); - /* Trigger a call to `on_thread_exit ()'. */ - pthread_exit (NULL); - return 0; } diff --git a/libguile/threads.h b/libguile/threads.h index b5e3c21..475af32 100644 --- a/libguile/threads.h +++ b/libguile/threads.h @@ -192,6 +192,10 @@ SCM_API void scm_dynwind_critical_section (SCM mutex); #ifdef BUILDING_LIBGUILE +/* Though we don't need the key for SCM_I_CURRENT_THREAD if we have TLS, + we do use it for cleanup purposes. */ +SCM_INTERNAL scm_i_pthread_key_t scm_i_thread_key; + # ifdef SCM_HAVE_THREAD_STORAGE_CLASS SCM_INTERNAL SCM_THREAD_LOCAL scm_i_thread *scm_i_current_thread; @@ -199,7 +203,6 @@ SCM_INTERNAL SCM_THREAD_LOCAL scm_i_thread *scm_i_current_thread; # else /* !SCM_HAVE_THREAD_STORAGE_CLASS */ -SCM_INTERNAL scm_i_pthread_key_t scm_i_thread_key; # define SCM_I_CURRENT_THREAD \ ((scm_i_thread *) scm_i_pthread_getspecific (scm_i_thread_key)) -- 1.7.3.4 [-- Attachment #3: Type: text/plain, Size: 25 bytes --] -- http://wingolog.org/ ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: Trouble joining with threads from C 2011-03-18 12:23 ` Andy Wingo @ 2011-03-20 23:11 ` Ludovic Courtès 2011-04-13 21:25 ` Ludovic Courtès 0 siblings, 1 reply; 12+ messages in thread From: Ludovic Courtès @ 2011-03-20 23:11 UTC (permalink / raw) To: guile-devel Hi! Thanks for the brave threading debugging. :-) Andy Wingo <wingo@pobox.com> writes: > No, the issue is elsewhere, that the thread-exit handlers were not being > called I just tried with 60582b7c2a495957012f9a20cd8691dc6307a850 and ‘on_thread_exit’ /is/ called after something like ‘(call-with-new-thread (lambda () #t))’. Am I missing something? > Would you mind submitting (and committing :) a test case? Adding it to > test-suite/standalone is probably the thing to do. Yes, that’d be nice (even better in a single commit so we see the fix and test are related.) Thanks, Ludo’. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Trouble joining with threads from C 2011-03-20 23:11 ` Ludovic Courtès @ 2011-04-13 21:25 ` Ludovic Courtès 2011-04-13 21:34 ` Ludovic Courtès 0 siblings, 1 reply; 12+ messages in thread From: Ludovic Courtès @ 2011-04-13 21:25 UTC (permalink / raw) To: guile-devel [-- Attachment #1: Type: text/plain, Size: 574 bytes --] ludo@gnu.org (Ludovic Courtès) writes: > Hi! Howdy! > Andy Wingo <wingo@pobox.com> writes: > >> No, the issue is elsewhere, that the thread-exit handlers were not being >> called > > I just tried with 60582b7c2a495957012f9a20cd8691dc6307a850 and > ‘on_thread_exit’ /is/ called after something like > ‘(call-with-new-thread (lambda () #t))’. The thread-exit handlers were not being called *for threads launched by scm_spawn_thread*. The patch below (against 60582b7c2a495957012f9a20cd8691dc6307a850) fixes it. Now to see what's happened since then... Ludo'. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: the patch --] [-- Type: text/x-patch, Size: 2977 bytes --] diff --git a/libguile/threads.c b/libguile/threads.c index e7347ad..1c90517 100644 --- a/libguile/threads.c +++ b/libguile/threads.c @@ -980,7 +980,11 @@ spawn_thread (void *d) { spawn_data *data = (spawn_data *)d; scm_i_pthread_detach (scm_i_pthread_self ()); + + scm_i_pthread_cleanup_push (scm_leave_guile_cleanup, NULL); scm_i_with_guile_and_parent (really_spawn, d, data->parent); + scm_i_pthread_cleanup_pop (1); + return NULL; } diff --git a/test-suite/standalone/Makefile.am b/test-suite/standalone/Makefile.am index b21edd2..b1f16f3 100644 --- a/test-suite/standalone/Makefile.am +++ b/test-suite/standalone/Makefile.am @@ -198,6 +198,11 @@ test_scm_with_guile_LDADD = $(LIBGUILE_LDADD) check_PROGRAMS += test-scm-with-guile TESTS += test-scm-with-guile +test_scm_spawn_thread_CFLAGS = ${test_cflags} +test_scm_spawn_thread_LDADD = $(LIBGUILE_LDADD) +check_PROGRAMS += test-scm-spawn-thread +TESTS += test-scm-spawn-thread + else EXTRA_DIST += test-with-guile-module.c test-scm-with-guile.c diff --git a/test-suite/standalone/test-scm-spawn-thread.c b/test-suite/standalone/test-scm-spawn-thread.c new file mode 100644 index 0000000..b632ab0 --- /dev/null +++ b/test-suite/standalone/test-scm-spawn-thread.c @@ -0,0 +1,62 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +/* Test whether a thread created with `scm_spawn_thread' can be joined. + See <http://thread.gmane.org/gmane.lisp.guile.devel/11804> for the + original report. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <libguile.h> + +#include <time.h> +#include <stdlib.h> + +static SCM +thread_main (void *data) +{ + return SCM_BOOL_T; +} + +static SCM +thread_handler (void *data, SCM key, SCM args) +{ + return SCM_BOOL_T; +} + +static void * +inner_main (void *data) +{ + SCM thread, timeout; + + thread = scm_spawn_thread (thread_main, 0, thread_handler, 0); + timeout = scm_from_unsigned_integer (time (NULL) + 10); + return (void *) scm_join_thread_timed (thread, timeout, SCM_BOOL_F); +} + +\f +int +main (int argc, char **argv) +{ + SCM result; + + result = PTR2SCM (scm_with_guile (inner_main, 0)); + return scm_is_true (result) ? EXIT_SUCCESS : EXIT_FAILURE; +} ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: Trouble joining with threads from C 2011-04-13 21:25 ` Ludovic Courtès @ 2011-04-13 21:34 ` Ludovic Courtès 2011-04-15 8:41 ` Andy Wingo 0 siblings, 1 reply; 12+ messages in thread From: Ludovic Courtès @ 2011-04-13 21:34 UTC (permalink / raw) To: guile-devel Hello, ludo@gnu.org (Ludovic Courtès) writes: > ludo@gnu.org (Ludovic Courtès) writes: >> Andy Wingo <wingo@pobox.com> writes: >> >>> No, the issue is elsewhere, that the thread-exit handlers were not being >>> called >> >> I just tried with 60582b7c2a495957012f9a20cd8691dc6307a850 and >> ‘on_thread_exit’ /is/ called after something like >> ‘(call-with-new-thread (lambda () #t))’. > > The thread-exit handlers were not being called *for threads launched by > scm_spawn_thread*. > > The patch below (against 60582b7c2a495957012f9a20cd8691dc6307a850) fixes it. After reviewing f60a7648d5926555c7760364a6fbb7dc0cf60720 (which addressed the same issue), I lean towards reverting it and instead applying the patch I just sent. The problem I see with f60a7648d5926555c7760364a6fbb7dc0cf60720 is that it re-introduces a pthread_key, even when using TLS, and make things a bit complex IMO. Thoughts? Besides, reverting it may fix --without-threads builds. Thanks, Ludo’. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Trouble joining with threads from C 2011-04-13 21:34 ` Ludovic Courtès @ 2011-04-15 8:41 ` Andy Wingo 2011-04-15 21:44 ` Ludovic Courtès 2011-04-25 13:53 ` Ludovic Courtès 0 siblings, 2 replies; 12+ messages in thread From: Andy Wingo @ 2011-04-15 8:41 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel Hi Ludovic, On Wed 13 Apr 2011 23:34, ludo@gnu.org (Ludovic Courtès) writes: > After reviewing f60a7648d5926555c7760364a6fbb7dc0cf60720 (which > addressed the same issue), I lean towards reverting it and instead > applying the patch I just sent. > > The problem I see with f60a7648d5926555c7760364a6fbb7dc0cf60720 is that > it re-introduces a pthread_key, even when using TLS, and make things a > bit complex IMO. The issue is that threads in Guile are not always spawned by Guile. It's true that of the two cases in which Guile spawned a thread, one of them wasn't getting the cleanup handlers called, and your patch fixes that; but that ignores the case of threads that are spawned by a user's program. For example in the following program: void* thread (void*) { scm_with_guile (do_something, NULL); scm_with_guile (do_something_else, NULL); return NULL; } int main () { pthread_t thr; pthread_create (&thr, NULL, thread, NULL); pthread_join (thr, NULL); return 0; } When do you propose that the cleanup handlers for the thread be called? As far as I understand things, reliably cleaning up after the thread *requires* the use of pthread_key with a destructor. It is the only way to attach a cleanup callback to a thread. It's true that the key is not used when TLS is available, except for its destructor capabilities, but it is not more complicated than before. I think they context that you are missing here is bug 32436. It does appear that I have introduced some bugs here: Mark's after-gc-hook not being called, and a failure to build --without-threads. For that I apologize. But these bugs are fixable. Consider bug 32436 for a moment: you can't fix that with pthread_cleanup_push. Does this explanation help? Let me know, Andy -- http://wingolog.org/ ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Trouble joining with threads from C 2011-04-15 8:41 ` Andy Wingo @ 2011-04-15 21:44 ` Ludovic Courtès 2011-04-16 15:55 ` Andy Wingo 2011-04-25 13:53 ` Ludovic Courtès 1 sibling, 1 reply; 12+ messages in thread From: Ludovic Courtès @ 2011-04-15 21:44 UTC (permalink / raw) To: Andy Wingo; +Cc: guile-devel Hi Andy! Thanks for your explanations. Andy Wingo <wingo@pobox.com> writes: > On Wed 13 Apr 2011 23:34, ludo@gnu.org (Ludovic Courtès) writes: > >> After reviewing f60a7648d5926555c7760364a6fbb7dc0cf60720 (which >> addressed the same issue), I lean towards reverting it and instead >> applying the patch I just sent. >> >> The problem I see with f60a7648d5926555c7760364a6fbb7dc0cf60720 is that >> it re-introduces a pthread_key, even when using TLS, and make things a >> bit complex IMO. > > The issue is that threads in Guile are not always spawned by Guile. > It's true that of the two cases in which Guile spawned a thread, one of > them wasn't getting the cleanup handlers called, and your patch fixes > that; but that ignores the case of threads that are spawned by a user's > program. Right, I was just focusing on Mark’s case, blissfully ignoring #32436. > For example in the following program: > > void* thread (void*) > { > scm_with_guile (do_something, NULL); > scm_with_guile (do_something_else, NULL); > return NULL; > } > > int main () > { > pthread_t thr; > pthread_create (&thr, NULL, thread, NULL); > pthread_join (thr, NULL); > return 0; > } > > When do you propose that the cleanup handlers for the thread be called? I’ll followup on this later, but currently it seems impossible to call GC_INIT from a thread other than the initial thread [0]. Thanks, Ludo’. [0] http://article.gmane.org/gmane.comp.programming.garbage-collection.boehmgc/4490 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Trouble joining with threads from C 2011-04-15 21:44 ` Ludovic Courtès @ 2011-04-16 15:55 ` Andy Wingo 0 siblings, 0 replies; 12+ messages in thread From: Andy Wingo @ 2011-04-16 15:55 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel Heya Ludo, On Fri 15 Apr 2011 23:44, ludo@gnu.org (Ludovic Courtès) writes: >> For example in the following program: >> >> void* thread (void*) >> { >> scm_with_guile (do_something, NULL); >> scm_with_guile (do_something_else, NULL); >> return NULL; >> } >> >> int main () >> { >> pthread_t thr; >> pthread_create (&thr, NULL, thread, NULL); >> pthread_join (thr, NULL); >> return 0; >> } >> >> When do you propose that the cleanup handlers for the thread be called? > > I’ll followup on this later, but currently it seems impossible to call > GC_INIT from a thread other than the initial thread [0]. Interesting; I had it working at some point, in the context of that other bug; anyway, the same considerations hold if you scm_init_guile in the main thread first. Cheers, Andy -- http://wingolog.org/ ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Trouble joining with threads from C 2011-04-15 8:41 ` Andy Wingo 2011-04-15 21:44 ` Ludovic Courtès @ 2011-04-25 13:53 ` Ludovic Courtès 2011-04-25 14:19 ` Andy Wingo 1 sibling, 1 reply; 12+ messages in thread From: Ludovic Courtès @ 2011-04-25 13:53 UTC (permalink / raw) To: guile-devel [-- Attachment #1: Type: text/plain, Size: 6853 bytes --] Hello! Andy Wingo <wingo@pobox.com> writes: > When do you propose that the cleanup handlers for the thread be called? > > As far as I understand things, reliably cleaning up after the thread > *requires* the use of pthread_key with a destructor. It is the only way > to attach a cleanup callback to a thread. It's true that the key is not > used when TLS is available, except for its destructor capabilities, but > it is not more complicated than before. > > I think they context that you are missing here is bug 32436. > > It does appear that I have introduced some bugs here: Mark's > after-gc-hook not being called, and a failure to build > --without-threads. For that I apologize. But these bugs are fixable. > Consider bug 32436 for a moment: you can't fix that with > pthread_cleanup_push. Attached are 3 tests: one for Mark’s bug, and two for #32436. Currently they all pass, but ‘test-scm-spawn-thread’ hits a libgc assertion failure (“Duplicate large block deallocation”) once every 5 runs or so: --8<---------------cut here---------------start------------->8--- (gdb) thread apply all bt Thread 3 (Thread 0x7ffff582e700 (LWP 15207)): #0 0x00007ffff62b220b in memset () from /nix/store/vxycd107wjbhcj720hzkw2px7s7kr724-glibc-2.12.2/lib/libc.so.6 #1 0x00007ffff6e8c6d8 in GC_generic_malloc (lb=524288, k=<value optimized out>) at ../malloc.c:193 #2 0x00007ffff7b36aad in make_vm () at vm.c:501 #3 0x00007ffff7b36b8e in scm_the_vm () at vm.c:578 #4 0x00007ffff7ac3190 in scm_call_4 (proc=0x778ab0, arg1=<value optimized out>, arg2=<value optimized out>, arg3=<value optimized out>, arg4=<value optimized out>) at eval.c:476 #5 0x00007ffff7aba283 in scm_i_with_continuation_barrier (body=0x7ffff7ab9a90 <c_body>, body_data=0x7ffff582dd80, handler=0x7ffff7ab9e60 <c_handler>, handler_data=0x7ffff582dd80, pre_unwind_handler=<value optimized out>, pre_unwind_handler_data=<value optimized out>) at continuations.c:450 #6 0x00007ffff7aba335 in scm_c_with_continuation_barrier (func=<value optimized out>, data=<value optimized out>) at continuations.c:546 #7 0x00007ffff7b3146a in with_guile_and_parent (base=0x7ffff582dde0, data=0x7ffff582de00) at threads.c:856 #8 0x00007ffff6e916b5 in GC_call_with_stack_base (fn=<value optimized out>, arg=<value optimized out>) at ../misc.c:1505 #9 0x00007ffff7b3109c in scm_i_with_guile_and_parent (d=<value optimized out>) at threads.c:899 #10 spawn_thread (d=<value optimized out>) at threads.c:1056 #11 0x00007ffff6e96791 in GC_inner_start_routine (sb=<value optimized out>, arg=<value optimized out>) at ../pthread_start.c:61 #12 0x00007ffff6e916b5 in GC_call_with_stack_base (fn=<value optimized out>, arg=<value optimized out>) at ../misc.c:1505 #13 0x00007ffff6c61cec in start_thread () from /nix/store/vxycd107wjbhcj720hzkw2px7s7kr724-glibc-2.12.2/lib/libpthread.so.0 #14 0x00007ffff63041ed in clone () from /nix/store/vxycd107wjbhcj720hzkw2px7s7kr724-glibc-2.12.2/lib/libc.so.6 Thread 2 (Thread 0x7ffff602f700 (LWP 15206)): #0 0x00007ffff626585e in raise () from /nix/store/vxycd107wjbhcj720hzkw2px7s7kr724-glibc-2.12.2/lib/libc.so.6 #1 0x00007ffff6266d16 in abort () from /nix/store/vxycd107wjbhcj720hzkw2px7s7kr724-glibc-2.12.2/lib/libc.so.6 #2 0x00007ffff6e90d9f in GC_abort (msg=0x7ffff6e98b50 "Duplicate large block deallocation") at ../misc.c:1409 #3 0x00007ffff6e85b3c in GC_freehblk (hbp=0x980000) at ../allchblk.c:852 #4 0x00007ffff6e977cb in GC_pthread_create (new_thread=0x7ffff602ee38, attr=0x0, start_routine=0x7ffff7b31060 <spawn_thread>, arg=0x7ffff602edb0) at ../pthread_support.c:1552 #5 0x00007ffff7b31cbc in scm_spawn_thread (body=<value optimized out>, body_data=<value optimized out>, handler=0x7ffff7b33f20 <scm_handle_by_message>, handler_data=0x7ffff7b72868) at threads.c:1078 #6 0x00007ffff7b0e1cc in start_signal_delivery_thread () at scmsigs.c:193 #7 0x00007ffff6c67c83 in pthread_once () from /nix/store/vxycd107wjbhcj720hzkw2px7s7kr724-glibc-2.12.2/lib/libpthread.so.0 #8 0x00007ffff7b3115d in on_thread_exit (v=0x96a600) at threads.c:692 #9 0x00007ffff6c61b29 in __nptl_deallocate_tsd () from /nix/store/vxycd107wjbhcj720hzkw2px7s7kr724-glibc-2.12.2/lib/libpthread.so.0 #10 0x00007ffff6c61cfa in start_thread () from /nix/store/vxycd107wjbhcj720hzkw2px7s7kr724-glibc-2.12.2/lib/libpthread.so.0 #11 0x00007ffff63041ed in clone () from /nix/store/vxycd107wjbhcj720hzkw2px7s7kr724-glibc-2.12.2/lib/libc.so.6 Thread 1 (Thread 0x7ffff7ff3700 (LWP 15205)): #0 0x00007ffff6c6692b in pthread_cond_timedwait@@GLIBC_2.3.2 () from /nix/store/vxycd107wjbhcj720hzkw2px7s7kr724-glibc-2.12.2/lib/libpthread.so.0 #1 0x00007ffff7b31e76 in scm_pthread_cond_timedwait (cond=0x662e88, mutex=0x96a628, wt=0x7fffffffcca0) at threads.c:1916 #2 0x00007ffff7b31fca in block_self (queue=0x981fc0, sleep_object=<value optimized out>, mutex=0x96a628, waittime=0x7fffffffcca0) at threads.c:431 #3 0x00007ffff7b321f9 in scm_join_thread_timed (thread=0x981ff0, timeout=<value optimized out>, timeoutval=<value optimized out>) at threads.c:1205 #4 0x00007ffff7ab9a9a in c_body (d=0x7fffffffcf30) at continuations.c:512 #5 0x00007ffff7b497b0 in vm_regular_engine (vm=0x6f38c0, program=0x7ffff7b72f72, argv=0x6f70a8, nargs=1) at vm-i-system.c:956 #6 0x00007ffff7ac31a3 in scm_call_4 (proc=0x778ab0, arg1=<value optimized out>, arg2=<value optimized out>, arg3=<value optimized out>, arg4=<value optimized out>) at eval.c:476 #7 0x00007ffff7aba283 in scm_i_with_continuation_barrier (body=0x7ffff7ab9a90 <c_body>, body_data=0x7fffffffcf30, handler=0x7ffff7ab9e60 <c_handler>, handler_data=0x7fffffffcf30, pre_unwind_handler=<value optimized out>, pre_unwind_handler_data=<value optimized out>) at continuations.c:450 #8 0x00007ffff7aba335 in scm_c_with_continuation_barrier (func=<value optimized out>, data=<value optimized out>) at continuations.c:546 #9 0x00007ffff7b3146a in with_guile_and_parent (base=0x7fffffffcf90, data=0x7fffffffcfb0) at threads.c:856 #10 0x00007ffff6e916b5 in GC_call_with_stack_base (fn=<value optimized out>, arg=<value optimized out>) at ../misc.c:1505 #11 0x00007ffff7b31598 in scm_i_with_guile_and_parent (func=<value optimized out>, data=<value optimized out>) at threads.c:899 #12 scm_with_guile (func=<value optimized out>, data=<value optimized out>) at threads.c:905 #13 0x00000000004008c0 in main (argc=<value optimized out>, argv=<value optimized out>) at test-scm-spawn-thread.c:60 --8<---------------cut here---------------end--------------->8--- This happens when calling ‘GC_pthread_create’ from a pthread key destructor, which appears to be problematic [0]. I haven’t been able to fix it or otherwise work around it though, so help welcome! :-) I think this is not a showstopper for 2.0.1. Thanks, Ludo’. [0] http://thread.gmane.org/gmane.comp.programming.garbage-collection.boehmgc/4502 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: the tests --] [-- Type: text/x-patch, Size: 8887 bytes --] From 257ee9f4449c82c4cf9d3cd9951e48df549667fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@gnu.org> Date: Fri, 22 Apr 2011 12:29:50 +0200 Subject: [PATCH] Add pthread-related tests. * test-suite/standalone/Makefile.am (test_scm_spawn_thread_CFLAGS, test_scm_spawn_thread_LDADD, test_pthread_create_CFLAGS, test_pthread_create_LDADD, test_pthread_create_secondary_CFLAGS, test_pthread_create_secondary_LDADD): New variables. (check_PROGRAMS)[BUILD_PTHREAD_SUPPORT]: Add `test-scm-spawn-thread', `test-pthread_create', `test-pthread_create-secondary'. (TESTS)[BUILD_PTHREAD_SUPPORT]: Likewise. * test-suite/standalone/test-scm-spawn-thread.c, test-suite/standalone/test-pthread-create.c, test-suite/standalone/test-pthread-create-secondary.c: New files. --- .gitignore | 3 + test-suite/standalone/Makefile.am | 15 ++++ .../standalone/test-pthread-create-secondary.c | 85 ++++++++++++++++++++ test-suite/standalone/test-pthread-create.c | 63 +++++++++++++++ test-suite/standalone/test-scm-spawn-thread.c | 62 ++++++++++++++ 5 files changed, 228 insertions(+), 0 deletions(-) create mode 100644 test-suite/standalone/test-pthread-create-secondary.c create mode 100644 test-suite/standalone/test-pthread-create.c create mode 100644 test-suite/standalone/test-scm-spawn-thread.c diff --git a/.gitignore b/.gitignore index f24e589..a0eeeca 100644 --- a/.gitignore +++ b/.gitignore @@ -139,3 +139,6 @@ INSTALL /.sc-start-* /lib/math.h /lib/sys/time.h +/test-suite/standalone/test-scm-spawn-thread +/test-suite/standalone/test-pthread-create +/test-suite/standalone/test-pthread-create-secondary diff --git a/test-suite/standalone/Makefile.am b/test-suite/standalone/Makefile.am index b21edd2..cf1fc4f 100644 --- a/test-suite/standalone/Makefile.am +++ b/test-suite/standalone/Makefile.am @@ -198,6 +198,21 @@ test_scm_with_guile_LDADD = $(LIBGUILE_LDADD) check_PROGRAMS += test-scm-with-guile TESTS += test-scm-with-guile +test_scm_spawn_thread_CFLAGS = ${test_cflags} +test_scm_spawn_thread_LDADD = $(LIBGUILE_LDADD) +check_PROGRAMS += test-scm-spawn-thread +TESTS += test-scm-spawn-thread + +test_pthread_create_CFLAGS = ${test_cflags} +test_pthread_create_LDADD = $(LIBGUILE_LDADD) +check_PROGRAMS += test-pthread-create +TESTS += test-pthread-create + +test_pthread_create_secondary_CFLAGS = ${test_cflags} $(BDW_GC_CFLAGS) +test_pthread_create_secondary_LDADD = $(LIBGUILE_LDADD) +check_PROGRAMS += test-pthread-create-secondary +TESTS += test-pthread-create-secondary + else EXTRA_DIST += test-with-guile-module.c test-scm-with-guile.c diff --git a/test-suite/standalone/test-pthread-create-secondary.c b/test-suite/standalone/test-pthread-create-secondary.c new file mode 100644 index 0000000..fe39c2a --- /dev/null +++ b/test-suite/standalone/test-pthread-create-secondary.c @@ -0,0 +1,85 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +/* Test whether threads created with `pthread_create' work, and whether + a secondary thread can call `scm_with_guile'. (bug #32436). */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <pthread.h> +#include <stdlib.h> +#include <libguile.h> + +#include <gc/gc_version.h> + + +/* Up to GC 7.2alpha5, calling `GC_INIT' from a secondary thread would + lead to a segfault. This was fixed in BDW-GC on 2011-04-16 by Ivan + Maidanski. See <http://thread.gmane.org/gmane.lisp.guile.bugs/5340> + for details. */ + +#if (GC_VERSION_MAJOR > 7) \ + || ((GC_VERSION_MAJOR == 7) && (GC_VERSION_MINOR > 2)) \ + || ((GC_VERSION_MAJOR == 7) && (GC_VERSION_MINOR == 2) \ + && (GC_ALPHA_VERSION > 5)) + +static void * +do_something (void *arg) +{ + scm_list_copy (scm_make_list (scm_from_int (1234), SCM_BOOL_T)); + scm_gc (); + return NULL; +} + +static void * +thread (void *arg) +{ + scm_with_guile (do_something, NULL); + return NULL; +} + +\f +int +main (int argc, char *argv[]) +{ + int i; + + for (i = 0; i < 77; i++) + { + pthread_t thr; + + pthread_create (&thr, NULL, thread, NULL); + pthread_join (thr, NULL); + } + + return EXIT_SUCCESS; +} + +\f +#else /* GC < 7.2 */ + +int +main (int argc, char *argv[]) +{ + /* Skip. */ + return 77; +} + +#endif /* GC < 7.2 */ diff --git a/test-suite/standalone/test-pthread-create.c b/test-suite/standalone/test-pthread-create.c new file mode 100644 index 0000000..8d9617b --- /dev/null +++ b/test-suite/standalone/test-pthread-create.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +/* Test whether threads created with `pthread_create' work (bug #32436) + when then main thread is the one that initializes Guile. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <pthread.h> +#include <stdlib.h> +#include <libguile.h> + +static void * +do_something (void *arg) +{ + scm_list_copy (scm_make_list (scm_from_int (1234), SCM_BOOL_T)); + scm_gc (); + return NULL; +} + +static void * +thread (void *arg) +{ + scm_with_guile (do_something, NULL); + return NULL; +} + +\f +int +main (int argc, char *argv[]) +{ + int i; + pthread_t thr; + + scm_init_guile (); + + do_something (NULL); + + for (i = 0; i < 77; i++) + { + pthread_create (&thr, NULL, thread, NULL); + pthread_join (thr, NULL); + } + + return EXIT_SUCCESS; +} diff --git a/test-suite/standalone/test-scm-spawn-thread.c b/test-suite/standalone/test-scm-spawn-thread.c new file mode 100644 index 0000000..b632ab0 --- /dev/null +++ b/test-suite/standalone/test-scm-spawn-thread.c @@ -0,0 +1,62 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +/* Test whether a thread created with `scm_spawn_thread' can be joined. + See <http://thread.gmane.org/gmane.lisp.guile.devel/11804> for the + original report. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <libguile.h> + +#include <time.h> +#include <stdlib.h> + +static SCM +thread_main (void *data) +{ + return SCM_BOOL_T; +} + +static SCM +thread_handler (void *data, SCM key, SCM args) +{ + return SCM_BOOL_T; +} + +static void * +inner_main (void *data) +{ + SCM thread, timeout; + + thread = scm_spawn_thread (thread_main, 0, thread_handler, 0); + timeout = scm_from_unsigned_integer (time (NULL) + 10); + return (void *) scm_join_thread_timed (thread, timeout, SCM_BOOL_F); +} + +\f +int +main (int argc, char **argv) +{ + SCM result; + + result = PTR2SCM (scm_with_guile (inner_main, 0)); + return scm_is_true (result) ? EXIT_SUCCESS : EXIT_FAILURE; +} -- 1.7.4.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: Trouble joining with threads from C 2011-04-25 13:53 ` Ludovic Courtès @ 2011-04-25 14:19 ` Andy Wingo 2011-04-25 14:49 ` Ludovic Courtès 0 siblings, 1 reply; 12+ messages in thread From: Andy Wingo @ 2011-04-25 14:19 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel On Mon 25 Apr 2011 15:53, ludo@gnu.org (Ludovic Courtès) writes: > Attached are 3 tests: one for Mark’s bug, and two for #32436. o/~ did you ever know that you're my heeee-roooo o/~ > Currently they all pass, but ‘test-scm-spawn-thread’ hits a libgc > assertion failure (“Duplicate large block deallocation”) once every 5 > runs or so: I guess we disable this one then? That code always seemed a little fishy to me: /* Ensure the signal handling thread has been launched, because we might be shutting it down. */ scm_i_ensure_signal_delivery_thread (); Perhaps we can avoid spawning a thread in the key destructor. Andy -- http://wingolog.org/ ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Trouble joining with threads from C 2011-04-25 14:19 ` Andy Wingo @ 2011-04-25 14:49 ` Ludovic Courtès 0 siblings, 0 replies; 12+ messages in thread From: Ludovic Courtès @ 2011-04-25 14:49 UTC (permalink / raw) To: Andy Wingo; +Cc: guile-devel Hello! Andy Wingo <wingo@pobox.com> writes: > On Mon 25 Apr 2011 15:53, ludo@gnu.org (Ludovic Courtès) writes: [...] >> Currently they all pass, but ‘test-scm-spawn-thread’ hits a libgc >> assertion failure (“Duplicate large block deallocation”) once every 5 >> runs or so: > > I guess we disable this one then? > > That code always seemed a little fishy to me: > > /* Ensure the signal handling thread has been launched, because we might be > shutting it down. */ > scm_i_ensure_signal_delivery_thread (); > > Perhaps we can avoid spawning a thread in the key destructor. I apparently found a fix: calling ‘scm_i_ensure_signal_delivery_thread’ in Guile mode. I *think* the stack of ‘GC_pthread_create’ wasn’t scanned, so the area pointed to by its variable ‘si’ would be reclaimed before the function completes, leading to the “duplicate deallocation” error. Pfffeww. Thanks, Ludo’. ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2011-04-25 14:49 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-03-07 5:56 Trouble joining with threads from C Mark H Weaver 2011-03-09 6:48 ` Mark H Weaver 2011-03-18 12:23 ` Andy Wingo 2011-03-20 23:11 ` Ludovic Courtès 2011-04-13 21:25 ` Ludovic Courtès 2011-04-13 21:34 ` Ludovic Courtès 2011-04-15 8:41 ` Andy Wingo 2011-04-15 21:44 ` Ludovic Courtès 2011-04-16 15:55 ` Andy Wingo 2011-04-25 13:53 ` Ludovic Courtès 2011-04-25 14:19 ` Andy Wingo 2011-04-25 14:49 ` Ludovic Courtès
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).