diff -Nur --exclude='*~' --exclude=deh.d unpatched_phobos/internal/gc/gc.d patched_phobos/internal/gc/gc.d
--- unpatched_phobos/internal/gc/gc.d	2008-02-06 03:35:44.000000000 +0100
+++ patched_phobos/internal/gc/gc.d	2008-02-06 15:20:57.000000000 +0100
@@ -309,7 +309,9 @@
 	debug(PRINTF) printf(" p = %p\n", p);
 	if (!(ti.next.flags() & 1))
 	    _gc.hasNoPointers(p);
-	if (isize == 1)
+	if (isize == 0)
+	    memset(p, 0, size);
+	else if (isize == 1)
 	    memset(p, *cast(ubyte*)q, size);
 	else if (isize == int.sizeof)
 	{
@@ -629,9 +631,12 @@
     size_t initsize = initializer.length;
 
     assert(sizeelem);
-    assert(initsize);
+    // assert(initsize);
+    // there's a bug that accidentally calls this function with
+    // types with zero initializers. Deal with it for now.
+    // \todo: find underlying cause
     assert(initsize <= sizeelem);
-    assert((sizeelem / initsize) * initsize == sizeelem);
+    assert(!initsize || (sizeelem / initsize) * initsize == sizeelem);
 
     debug(PRINTF)
     {
@@ -703,8 +708,12 @@
 	}
 
 	auto q = initializer.ptr;	// pointer to initializer
-
-	if (newsize > size)
+	
+	if (initsize == 0)
+	{
+	    memset(newdata + size, 0, newsize - size);
+	}
+	else if (newsize > size)
 	{
 	    if (initsize == 1)
 	    {
diff -Nur --exclude='*~' --exclude=deh.d unpatched_phobos/internal/gc/gcx.d patched_phobos/internal/gc/gcx.d
--- unpatched_phobos/internal/gc/gcx.d	2008-02-06 03:35:44.000000000 +0100
+++ patched_phobos/internal/gc/gcx.d	2008-02-06 03:28:17.000000000 +0100
@@ -10,6 +10,8 @@
    Modified by David Friedman, July 2006
 */
 
+private import std.gc, std.stack;
+
 // D Garbage Collector implementation
 
 /************** Debugging ***************************/
@@ -1642,6 +1644,7 @@
 
 		if (t && t.getState() == Thread.TS.RUNNING)
 		{
+		    if (t.isSelf()) t.stack.lastESP = Thread.getESP();
 		    if (noStack && threads.length == 1)
 			break;
 
@@ -1655,32 +1658,9 @@
 			    assert(0);
 			}
 			debug (PRINTF) printf("mt scan stack bot = %x, top = %x\n", context.Esp, t.stackBottom);
-			mark(cast(void *)context.Esp, t.stackBottom);
+			//mark(cast(void *)context.Esp, t.stackBottom);
 			mark(&context.Edi, &context.Eip);
 		    }
-		    else version (GNU)
-		    {
-			if (t.isSelf())
-			    t.stackTop = Thread.getESP();
-
-			//%%fry printf("top=%08x bot=%08x ext=%08x\n", t.stackTop, t.stackBottom, Thread.getESP());//%%try
-			version (STACKGROWSDOWN)
-			    mark(t.stackTop, t.stackBottom);
-			else
-			    mark(t.stackBottom, t.stackTop);
-		    }
-		    else version (linux)
-		    {
-			// The registers are already stored in the stack
-			//printf("Thread: ESP = x%x, stackBottom = x%x, isSelf = %d\n", Thread.getESP(), t.stackBottom, t.isSelf());
-			if (t.isSelf())
-			    t.stackTop = Thread.getESP();
-
-			version (STACKGROWSDOWN)
-			    mark(t.stackTop, t.stackBottom);
-			else
-			    mark(t.stackBottom, t.stackTop);
-		    }
 		}
 	    }
 	}
@@ -1710,6 +1690,15 @@
 	    mark(ranges[n].pbot, ranges[n].ptop);
 	}
 	//log--;
+	// Scan stacks LL
+        auto cur = stacks;
+	while (cur) {
+	    version(STACKGROWSDOWN)
+		mark(cur.value.lastESP, cur.value.End);
+	    else
+		mark(cur.value.Start, cur.value.lastESP);
+	    cur = cur.next;
+	}
 
 	debug(COLLECT_PRINTF) printf("\tscan heap\n");
 	while (anychanges)
diff -Nur --exclude='*~' --exclude=deh.d unpatched_phobos/std/mmfile.d patched_phobos/std/mmfile.d
--- unpatched_phobos/std/mmfile.d	2008-02-06 03:35:40.000000000 +0100
+++ patched_phobos/std/mmfile.d	2008-02-06 03:02:31.000000000 +0100
@@ -193,31 +193,35 @@
 			    default:
 				assert(0);
 			}
-		
-			if (useWfuncs)
+			if (filename)
 			{
-				wchar* namez = std.utf.toUTF16z(filename);
-				hFile = CreateFileW(namez,
-						dwDesiredAccess2,
-						dwShareMode,
-						null,
-						dwCreationDisposition,
-						FILE_ATTRIBUTE_NORMAL,
-						cast(HANDLE)null);
+				if (useWfuncs)
+				{
+					wchar* namez = std.utf.toUTF16z(filename);
+					hFile = CreateFileW(namez,
+							dwDesiredAccess2,
+							dwShareMode,
+							null,
+							dwCreationDisposition,
+							FILE_ATTRIBUTE_NORMAL,
+							cast(HANDLE)null);
+				}
+				else
+				{
+					char* namez = std.file.toMBSz(filename);
+					hFile = CreateFileA(namez,
+							dwDesiredAccess2,
+							dwShareMode,
+							null,
+							dwCreationDisposition,
+							FILE_ATTRIBUTE_NORMAL,
+							cast(HANDLE)null);
+				}
+				if (hFile == INVALID_HANDLE_VALUE)
+					goto err1;
 			}
 			else
-			{
-				char* namez = std.file.toMBSz(filename);
-				hFile = CreateFileA(namez,
-						dwDesiredAccess2,
-						dwShareMode,
-						null,
-						dwCreationDisposition,
-						FILE_ATTRIBUTE_NORMAL,
-						cast(HANDLE)null);
-			}
-			if (hFile == INVALID_HANDLE_VALUE)
-				goto err1;
+				hFile = null;
 		
 			int hi = cast(int)(size>>32);
 			hFileMap = CreateFileMappingA(hFile, null, flProtect, hi, cast(uint)size, null);
@@ -360,7 +364,7 @@
 				errNo();
 			hFileMap = null;
 
-			if (hFile != INVALID_HANDLE_VALUE && CloseHandle(hFile) != TRUE)
+			if (hFile && hFile != INVALID_HANDLE_VALUE && CloseHandle(hFile) != TRUE)
 				errNo();
 			hFile = INVALID_HANDLE_VALUE;
 		}
diff -Nur --exclude='*~' --exclude=deh.d unpatched_phobos/std/stack.d patched_phobos/std/stack.d
--- unpatched_phobos/std/stack.d	1970-01-01 01:00:00.000000000 +0100
+++ patched_phobos/std/stack.d	2008-02-06 05:27:35.000000000 +0100
@@ -0,0 +1,75 @@
+module std.stack;
+import std.string, std.stdio;
+
+struct Stack {
+  void* Start, End;
+  void* lastESP;
+  string toString() {
+    return format("[", Start, " -> ", End, " @", lastESP, "]");
+  }
+  bool contains(void* ptr) { return ptr >= Start && ptr <= End; }
+}
+
+struct LinkedList(T) {
+  LinkedList* next;
+  T value;
+  string toString() {
+    auto cur = this;
+    string res;
+    while (cur) {
+      res ~= format(value, " -> ");
+      cur = cur.next;
+    }
+    return res ~ "null";
+  }
+}
+
+void ll_push(T, U)(ref T list, U what) {
+  static assert(is(T==LinkedList!(U)*));
+  auto nlist = new LinkedList!(U);
+  nlist.next = list;
+  nlist.value = what;
+  list = nlist;
+}
+
+void ll_delete(T, U)(ref T list, U value) {
+  if (list && list.value == value) { list = list.next; return; }
+  auto cur = list;
+  if (cur) while (cur.next) {
+    if (cur.next.value == value) { cur.next = cur.next.next; return; }
+    cur = cur.next;
+  }
+  throw new Exception(format("Value not found in linked list (", list, ")"));
+}
+
+LinkedList!(Stack*) *stacks;
+
+Stack* addStack(void* from, void* to) {
+  auto st = new Stack;
+  st.Start=from; st.End=to;
+  ll_push(stacks, st);
+  return st;
+}
+
+void delStack(Stack* which) {
+  ll_delete(stacks, which);
+}
+
+void updateESP(void* newESP) {
+  auto cur = stacks;
+  while (cur) {
+    if (newESP >= cur.value.Start && newESP <= cur.value.End) {
+      cur.value.lastESP = newESP;
+      return;
+    }
+    cur = cur.next;
+  }
+  Stack[] meep;
+  cur = stacks;
+  while (cur) {
+    meep ~= *cur.value;
+    cur = cur.next;
+  }
+  writefln("ESP (", newESP, ") not in any known stack (", meep, ")");
+  asm { int 3; }
+}
diff -Nur --exclude='*~' --exclude=deh.d unpatched_phobos/std/thread.d patched_phobos/std/thread.d
--- unpatched_phobos/std/thread.d	2008-02-06 03:35:42.000000000 +0100
+++ patched_phobos/std/thread.d	2008-02-06 05:27:17.000000000 +0100
@@ -39,6 +39,7 @@
  */
 
 module std.thread;
+import std.stack;
 
 //debug=thread;
 
@@ -80,6 +81,12 @@
  */
 class Thread
 {
+    public static void* getESP()
+    {
+	void* res;
+	asm { mov res, ESP; }
+	return res;
+    }
     /**
      * Constructor used by classes derived from Thread that override main(). 
      * The optional stacksize parameter default value of 0 will cause threads
@@ -88,6 +95,7 @@
     this(size_t stacksize = 0)
     {
 	this.stacksize = stacksize;
+	stack = addStack(null, null);
     }
 
     /**
@@ -98,6 +106,7 @@
 	this.fp = fp;
 	this.arg = arg;
 	this.stacksize = stacksize;
+        stack = addStack(null, null);
     }
 
     /**
@@ -107,6 +116,7 @@
     {
 	this.dg = dg;
 	this.stacksize = stacksize;
+        stack = addStack(null, null);
     }
 
     /**
@@ -115,7 +125,7 @@
      */
     thread_hdl hdl;
 
-    void* stackBottom;
+    Stack* stack; // the stack this thread is currently executing. NOT the main stack.
 
     /**
      * Create a new thread and start it running. The new thread initializes
@@ -406,7 +416,10 @@
 	int result;
 
 	debug (thread) printf("Starting thread %d\n", t.idx);
-	t.stackBottom = os_query_stackBottom();
+	t.stack.End = os_query_stackBottom();
+        auto size = t.stacksize;
+        if (!size) size = 1024*1024;
+        t.stack.Start = t.stack.End - size;
 	try
 	{
 	    result = t.run();
@@ -440,7 +453,10 @@
 	t.state = TS.RUNNING;
 	t.id = GetCurrentThreadId();
 	t.hdl = Thread.getCurrentThreadHandle();
-	t.stackBottom = os_query_stackBottom();
+	t.stack.End = os_query_stackBottom();
+        auto size = t.stacksize;
+	if (!size) size = 1024*1024; // default
+        t.stack.Start = t.stack.End - size;
 
 	assert(!allThreads[0]);
 	allThreads[0] = t;
@@ -571,8 +587,7 @@
     }
 
     pthread_t id;
-    void* stackBottom;
-    void* stackTop;
+    Stack* stack;
 
     void start()
     {
@@ -594,7 +609,7 @@
 		}
 	    }
 	    nthreads++;
-
+	
 	    state = TS.RUNNING;
 	    int result;
 	    //printf("creating thread x%x\n", this);
@@ -813,7 +828,6 @@
 	    }
 	    else
 	    {   int result;
-
 		result = pthread_kill(id, SIGUSR2);
 		if (result)
 		    error("cannot resume");
@@ -866,7 +880,7 @@
 		    result = pthread_kill(t.id, SIGUSR1);
 		    if (result)
 			getThis().error("cannot pause");
-		    else
+		else
 			npause++;	// count of paused threads
 		}
 	    }
@@ -960,6 +974,7 @@
 
 	if (pthread_cond_init(&waitCond, null))
 	    error("cannot initialize wait condition");
+	stack = addStack(null, null);
     }
 
     /************************************************
@@ -976,11 +991,14 @@
 	// Need to set t.id here, because thread is off and running
 	// before pthread_create() sets it.
 	t.id = pthread_self();
+        t.stack.End = getESP();
+        size_t stacksize;
+        pthread_attr_getstacksize(&t.threadAttrs, &stacksize);
+        t.stack.Start = t.stack.End - stacksize; // accurate enough
 
 	version(skyos)
 	    installSignalHandlers();
 
-	t.stackBottom = getESP();
 	try
 	{
 	    if(t.state == TS.RUNNING)
@@ -1018,7 +1036,10 @@
 
 	t.state = TS.RUNNING;
 	t.id = pthread_self();
-	t.stackBottom = cast(void*) _d_gcc_query_stack_origin();
+	t.stack.End = cast(void*) _d_gcc_query_stack_origin();
+        size_t stacksize;
+        pthread_attr_getstacksize(&t.threadAttrs, &stacksize);
+        t.stack.Start = t.stack.End - stacksize;
 
 	assert(!allThreads[0]);
 	allThreads[0] = t;
@@ -1092,7 +1113,8 @@
 	    assert(result == 0);
 
 	    Thread t = getThis();
-	    t.stackTop = getESP();
+	    auto esp = getESP();
+	    if (t.stack.contains(esp)) t.stack.lastESP = esp;
 	    t.flags &= ~1;
 	    flagSuspend.signal();
 	    while (1)
@@ -1145,8 +1167,7 @@
 	private static Thread _instance;
 	static uint nthreads = 1;
 
-	void* stackBottom;
-	void* stackTop;
+	Stack* stack;
 	enum TS
 	{
 	    INITIAL,
