diff --git a/src/Makefile.in b/src/Makefile.in
index 08387f8c37eeb83c66b4bd4fa0f5b4a5aa52f590..015c5ae89e5bf48dae4fc0bd232a7e56578f2019 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile.in,v 1.271 2001/09/02 01:36:14 marcus Exp $
+# $Id: Makefile.in,v 1.272 2001/09/18 22:59:56 hubbe Exp $
 #
 
 # This line is needed on some machines.
@@ -384,7 +384,7 @@ install_interactive: pike hilfe pike-module aclocal
 # tidy up a bit
 tidy:
 	-rm -f *.fail *.o *.obj *.pp *.protos core y.output y.tab.c y.tab.h
-	-rm -f $(TMP_BINDIR)/core *.o *.i *.i~ testsuite
+	-rm -f $(TMP_BINDIR)/core *.o *.i *.i~ testsuite dynloadtest*
 
 # make clean
 clean: tidy
@@ -440,6 +440,19 @@ just_verify: module_testsuites testsuite master-stamp
 	if test "$(TESTARGS)" = "" ; then args="-a" ; else args="$(TESTARGS)" ; fi; \
 	$(RUNPIKE) $(TMP_BINDIR)/test_pike.pike $$args
 
+# Testsuite for dynamic loading debugging
+test_dlopen: dynloadtest.sh
+	sh ./dynloadtest.sh
+
+dynloadtest.sh: $(SRCDIR)/test_dynamic_loading.in
+	m4 "$<" >"$@"
+
+dynloadtest.c: dynamic_load.c
+
+dynloadtest: dynloadtest.o @EXTRA_OBJS@ fdlib.o port.o
+	$(LD) $(LDFLAGS) dynloadtest.o @EXTRA_OBJS@ fdlib.o port.o $(LIBS) -o dynloadtest
+
+
 tinstall: aclocal master-stamp aclocal
 	-rm -rf test-install
 	$(RUNPIKE) $(TMP_BINDIR)/install.pike $(INSTALLARGS) pike_name="test-pike" lib_prefix="$(lib_prefix)" TMP_LIBDIR="$(TMP_LIBDIR)" LIBDIR_SRC="$(LIBDIR_SRC)" SRCDIR="$(SRCDIR)" prefix="./test-install" MANDIR_SRC="$(MANDIR_SRC)" man_prefix="$(man_prefix)" fakeroot="$(buildroot)" PIKE_MODULE_RELOC="$(PIKE_MODULE_RELOC)"
diff --git a/src/dynamic_load.c b/src/dynamic_load.c
index 8b03cc8ba97b87f353c2da2f582cbc0ec0c4c6b4..46e373c55702620898d216c1987c5926169bb695 100644
--- a/src/dynamic_load.c
+++ b/src/dynamic_load.c
@@ -1,4 +1,10 @@
-#ifndef TESTING
+#ifdef TESTING
+#define NO_PIKE_INCLUDES
+#define CREATE_MAIN
+#define NO_PIKE_GUTS
+#endif
+
+#ifndef NO_PIKE_INCLUDES
 #  include "global.h"
 #  include "interpret.h"
 #  include "constants.h"
@@ -9,7 +15,7 @@
 #  include "main.h"
 #  include "constants.h"
 
-RCSID("$Id: dynamic_load.c,v 1.55 2001/09/11 05:42:20 hubbe Exp $");
+RCSID("$Id: dynamic_load.c,v 1.56 2001/09/18 22:59:56 hubbe Exp $");
 
 #else /* TESTING */
 
@@ -292,7 +298,7 @@ static void *dlclose(void *module)
 #define RTLD_GLOBAL 0 
 #endif
 
-#ifndef TESTING
+#ifndef NO_PIKE_GUTS
 
 #if defined(HAVE_DLOPEN) || defined(USE_DLD) || defined(USE_HPUX_DL) || defined(USE_LOADLIBRARY)
 #define USE_DYNAMIC_MODULES
@@ -471,7 +477,9 @@ void free_dynamic_load(void)
 }
 
 
-#else /* TESTING */
+#endif /* NO_PIKE_GUTS */
+
+#ifdef CREATE_MAIN
 #include <stdio.h>
 
 int main()
@@ -496,4 +504,4 @@ int main()
   fprintf(stderr,"testfunc returned!\n");
   exit(1);
 }
-#endif
+#endif /* CREATE_MAIN */
diff --git a/src/fdlib.c b/src/fdlib.c
index 5bba2d2b48c13f33d8ee3f8fc9a7a046606d24a8..e5090d64a0697573acd466488112717993a4e373 100644
--- a/src/fdlib.c
+++ b/src/fdlib.c
@@ -3,7 +3,7 @@
 #include "pike_error.h"
 #include <math.h>
 
-RCSID("$Id: fdlib.c,v 1.48 2001/04/23 19:06:53 marcus Exp $");
+RCSID("$Id: fdlib.c,v 1.49 2001/09/18 22:59:56 hubbe Exp $");
 
 #ifdef HAVE_WINSOCK_H
 
@@ -25,6 +25,38 @@ int first_free_handle;
 #define FDDEBUG(X)
 #endif
 
+#ifdef PIKE_DEBUG
+static int IsValidHandle(HANDLE h)
+{
+  __try {
+    HANDLE ret;
+    if(DuplicateHandle(GetCurrentProcess(),
+			h,
+			GetCurrentProcess(),
+			&ret,
+			0,
+			0,
+			DUPLICATE_SAME_ACCESS))
+    {
+      CloseHandle(ret);
+    }
+  }
+
+  __except (1) {
+    return 0;
+  }
+
+  return 1;
+}
+
+PMOD_EXPORT HANDLE CheckValidHandle(HANDLE h)
+{
+  if(!IsValidHandle(h))
+    fatal("Invalid handle!\n");
+  return h;
+}
+#endif
+
 PMOD_EXPORT char *debug_fd_info(int fd)
 {
   if(fd<0)
diff --git a/src/test_dynamic_loading.in b/src/test_dynamic_loading.in
new file mode 100644
index 0000000000000000000000000000000000000000..b0976102884200763cf3033d0ef7e9c20503fbff
--- /dev/null
+++ b/src/test_dynamic_loading.in
@@ -0,0 +1,192 @@
+#!/bin/sh
+dnl This is a M4|sh script
+
+changequote([[,]])
+define([[TESTNUM]],0)
+
+define([[Tlow_test]],[[
+  define([[TESTNUM]],incr(TESTNUM))
+  echo "======= test TESTNUM ======="
+  $1
+  if ./dynloadtest ; then
+    echo "Test TESTNUM ok!"
+  else
+    echo "Test TESTNUM failed!"
+    for c in MODC
+    do
+      echo ==================== $c =======================
+      cat $c
+      echo ----------------------------------------------------------
+    done
+  fi
+]])dnl
+
+
+define([[Tmodule]],[[
+  define([[MODOBJ]],[[]])
+  define([[MODC]],[[]])
+  $2
+  if make --no-print-directory \
+   -f modules/dynamic_module_makefile \
+   SRCDIR="`dirname '__file__'`" \
+   TMP_BINDIR="`dirname '__file__'`/../bin" \
+   MODULE_BASE=modules \
+   OBJS="MODOBJ" \
+   MODNAME=dynloadtestmod$1 \
+   module.so
+   mv module.so dynloadtestmod$1.so ; then
+    :
+  else
+    echo Failed to compile test module!
+  fi
+  rm -f MODOBJ
+]])dnl
+
+define([[Tmodulefile]],[[
+define([[MODOBJ]],MODOBJ dynloadtestmod$1.o)
+define([[MODC]],MODC dynloadtestmod$1.c)
+cat >dynloadtestmod$1.c <<EOF
+#include "dynloadtest.h"
+$2
+EOF
+]])dnl
+
+define([[Tmod]],[[
+  Tmodule([[]],[[
+    Tmodulefile([[]],[[$1]])
+  ]])
+]])dnl
+
+define([[Tprog]],[[
+rm -f dynloadtest dynloadtest.o dynloadtest.c
+cat >dynloadtest.h <<EOF
+$1
+EOF
+cat >dynloadtest.c <<EOF
+#include "dynloadtest.h"
+$2
+EOF
+
+if make --no-print-directory dynloadtest ; then
+  :
+else
+  echo "Failed to compile test program"
+  cat dynloadtest.c
+  exit 1
+fi
+
+
+]])dnl
+
+
+Tprog([[
+#ifdef __NT__
+#define EXPORT __declspec(dllexport)
+#else
+#define EXPORT 
+#endif
+
+  extern int integer;
+  extern char * strptr;
+  int neg_func(int x);
+  int sub_one_func(int x);
+  extern int (*funcptr)(int);
+  int call_funcptr(int z);
+]],[[
+#define NO_PIKE_GUTS
+#include "dynamic_load.c"
+
+#line 1
+
+int integer = 17;
+
+char *strptr="strptr";
+
+int neg_func(int x)
+{
+  return -x;
+}
+
+int sub_one_func(int x)
+{
+  return x-1;
+}
+
+int (*funcptr)(int) = neg_func;
+
+int call_funcptr(int z)
+{
+  return funcptr(z);
+}
+
+char **ARGV;
+int main(int argc, char **argv)
+{
+  void *module,*fun;
+  ARGV=argv;
+  dlinit();
+  module=dlopen("./dynloadtestmod.so",RTLD_NOW);
+  if(!module)
+  {
+    fprintf(stderr,"Failed to link dlmodtest.so: %s\n",dlerror());
+    exit(1);
+  }
+  fun=dlsym(module,"foo");
+  if(!fun) fun=dlsym(module,"_foo");
+  if(!fun)
+  {
+    fprintf(stderr,"Failed to find function foo: %s\n",dlerror());
+    exit(1);
+  }
+  exit( ((int (*)(void))fun)() );
+}
+
+DECLSPEC(noreturn) void debug_fatal(const char *fmt, ...) ATTRIBUTE((noreturn,format (printf, 1, 2)))
+{
+  va_list args;
+  va_start(args,fmt);
+  (void)VFPRINTF(stderr, fmt, args);
+  fflush(stderr);
+  abort();
+}
+
+]])
+
+
+define([[TTest]],[[Tlow_test(Tmod([[$1]]))]])
+
+TTest( [[ EXPORT int foo() { return 0; } ]] )
+TTest( [[ EXPORT int foo() { exit(0); } ]] )
+TTest( [[ EXPORT int foo() { return integer != 17; } ]] )
+TTest( [[ EXPORT int foo() { return strcmp(strptr,"strptr"); } ]] )
+TTest( [[ EXPORT int foo() { return neg_func(-18) != 18; } ]] )
+TTest( [[ EXPORT int foo() { return sub_one_func(-18) != -19; } ]] )
+TTest( [[ EXPORT int foo() { return call_funcptr(-18) != 18; } ]] )
+
+TTest( [[
+EXPORT int foo()
+{
+  funcptr=sub_one_func;
+  return call_funcptr(-18) != -19;
+}
+]] )
+
+TTest( [[
+EXPORT int foo()
+{
+  funcptr=sub_one_func;
+  return call_funcptr(-18) != sub_one_func(-18);
+}
+]] )
+
+TTest( [[
+
+int bar(int q) { return 4711; }
+
+EXPORT int foo()
+{
+  funcptr=bar;
+  return call_funcptr(-18) != 4711;
+}
+]] )
+
diff --git a/src/threads.c b/src/threads.c
index 247b3f97acdc9ac688da526e8d156d0a64bce49c..3000ed13770b82936f920789673c1756a657b4f0 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -1,5 +1,5 @@
 #include "global.h"
-RCSID("$Id: threads.c,v 1.163 2001/09/06 00:20:59 hubbe Exp $");
+RCSID("$Id: threads.c,v 1.164 2001/09/18 22:59:57 hubbe Exp $");
 
 PMOD_EXPORT int num_threads = 1;
 PMOD_EXPORT int threads_disabled = 0;
@@ -81,36 +81,7 @@ int low_nt_create_thread(unsigned Pike_stack_size,
 
 
 #ifdef PIKE_DEBUG
-static int IsValidHandle(HANDLE h)
-{
-  __try {
-    HANDLE ret;
-    if(DuplicateHandle(GetCurrentProcess(),
-			h,
-			GetCurrentProcess(),
-			&ret,
-			0,
-			0,
-			DUPLICATE_SAME_ACCESS))
-    {
-      CloseHandle(ret);
-    }
-  }
-
-  __except (1) {
-    return 0;
-  }
-
-  return 1;
-}
-
-PMOD_EXPORT HANDLE CheckValidHandle(HANDLE h)
-{
-  if(!IsValidHandle(h))
-    fatal("Invalid handle!\n");
-  return h;
-}
-
+PMOD_EXPORT HANDLE CheckValidHandle(HANDLE h);
 #endif
 
 #endif
@@ -1844,6 +1815,7 @@ void th_cleanup(void)
     destruct(Pike_interpreter.thread_id);
     free_object(Pike_interpreter.thread_id);
     Pike_interpreter.thread_id=0;
+    destruct_objects_to_destruct_cb();
   }
 
   if(mutex_key)