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);