diff --git a/src/module.c b/src/module.c index bb2b42dc7b03ae63ecd7c15a439d488b7c4510cb..892ef46a4e6bc5dabba539ed83bb3433bfa33e20 100644 --- a/src/module.c +++ b/src/module.c @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: module.c,v 1.56 2008/08/05 21:10:17 mast Exp $ +|| $Id: module.c,v 1.57 2008/08/05 21:23:46 mast Exp $ */ #include "global.h" @@ -148,9 +148,11 @@ static void exit_builtin_modules(void) cleanup_gc(); cleanup_pike_types(); +#ifdef PIKE_THREADS /* This zaps Pike_interpreter.thread_state among other things, so * THREADS_ALLOW/DISALLOW are NOPs beyond this point. */ th_cleanup(); +#endif exit_pike_security(); free_svalue(& throw_value); @@ -162,7 +164,7 @@ static void exit_builtin_modules(void) { int leak_found = 0; -#ifdef _REENTRANT +#ifdef PIKE_THREADS if(count_pike_threads()) { fprintf(stderr,"Byte counting aborted, because all threads have not exited properly.\n"); @@ -437,10 +439,14 @@ void exit_modules(void) size_t count; if (exit_with_cleanup) { - /* Destruct all remaining objects while we have a proper execution - * environment. The downside is that the leak report below will - * always report destructed objects. We use the gc in a special mode - * for this to get a reasonably sane destruct order. */ + /* Kill the threads and destruct all remaining objects while we + * have a proper execution environment. The downside is that the + * leak report below will always report destructed objects. We use + * the gc in a special mode for this to get a reasonably sane + * destruct order. */ +#ifdef PIKE_THREADS + cleanup_all_other_threads(); +#endif gc_destruct_everything = 1; count = do_gc (NULL, 1); while (count) { diff --git a/src/threads.c b/src/threads.c index 57c78c4d107f55171bf06ae18e5dac839dca325b..775a11824cdd409ba7b6a0f74aa94eadf2544d7c 100644 --- a/src/threads.c +++ b/src/threads.c @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: threads.c,v 1.261 2008/08/05 20:43:25 mast Exp $ +|| $Id: threads.c,v 1.262 2008/08/05 21:23:46 mast Exp $ */ #include "global.h" @@ -1911,6 +1911,19 @@ static void f_thread_id_interrupt(INT32 args) push_int(0); } +static void low_thread_kill (struct thread_state *th) +{ + if (!(th->flags & THREAD_FLAG_SIGNAL_MASK)) { + num_pending_interrupts++; + if (!thread_interrupt_callback) { + thread_interrupt_callback = + add_to_callback(&evaluator_callbacks, check_thread_interrupt, 0, 0); + } + /* FIXME: Actually interrupt the thread. */ + } + th->flags |= THREAD_FLAG_TERM; +} + /*! @decl void kill() *! *! Interrupt the thread, and terminate it. @@ -1921,16 +1934,7 @@ static void f_thread_id_interrupt(INT32 args) static void f_thread_id_kill(INT32 args) { pop_n_elems(args); - - if (!(THIS_THREAD->flags & THREAD_FLAG_SIGNAL_MASK)) { - num_pending_interrupts++; - if (!thread_interrupt_callback) { - thread_interrupt_callback = - add_to_callback(&evaluator_callbacks, check_thread_interrupt, 0, 0); - } - /* FIXME: Actually interrupt the thread. */ - } - THIS_THREAD->flags |= THREAD_FLAG_TERM; + low_thread_kill (THIS_THREAD); push_int(0); } @@ -2433,6 +2437,44 @@ void th_init(void) thread_table_insert(Pike_interpreter.thread_state); } +#ifdef DO_PIKE_CLEANUP +void cleanup_all_other_threads (void) +{ + int i, num_kills = num_pending_interrupts; + time_t timeout = time (NULL) + 2; + + mt_lock (&thread_table_lock); + for (i = 0; i < THREAD_TABLE_SIZE; i++) { + struct thread_state *th; + for (th = thread_table_chains[i]; th; th = th->hashlink) + if (th != Pike_interpreter.thread_state) { + low_thread_kill (th); + num_kills++; + } + } + mt_unlock (&thread_table_lock); + + while (num_pending_interrupts && time (NULL) < timeout) { + THREADS_ALLOW(); +#ifdef __NT__ + Sleep (1); +#elif defined (HAVE_USLEEP) + usleep (1000); +#else + sleep (1); +#endif + THREADS_DISALLOW(); + } + + if (num_kills) { + fprintf (stderr, "Killed %d thread(s)", num_kills - num_pending_interrupts); + if (num_pending_interrupts) + fprintf (stderr, ", %d haven't responded", num_pending_interrupts); + fputs (".\n", stderr); + } +} +#endif + void th_cleanup(void) { th_running = 0; diff --git a/src/threads.h b/src/threads.h index e2b5f41b35c162cef6a303e15bf838b4be563f05..5b7dfaf275e413bf34e77e5715275950fe22b3a1 100644 --- a/src/threads.h +++ b/src/threads.h @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: threads.h,v 1.135 2008/08/05 20:47:27 mast Exp $ +|| $Id: threads.h,v 1.136 2008/08/05 21:23:46 mast Exp $ */ #ifndef THREADS_H @@ -103,6 +103,7 @@ void f_thread_local_get(INT32 args); void f_thread_local_set(INT32 args); void low_th_init(void); void th_init(void); +void cleanup_all_other_threads (void); void th_cleanup(void); int th_num_idle_farmers(void); int th_num_farmers(void);