Index: /trunk/ccl/lisp-kernel/x86-exceptions.c
===================================================================
--- /trunk/ccl/lisp-kernel/x86-exceptions.c	(revision 5613)
+++ /trunk/ccl/lisp-kernel/x86-exceptions.c	(revision 5614)
@@ -32,4 +32,9 @@
 #include <linux/prctl.h>
 #endif
+#ifdef DARWIN
+#include <sysexits.h>
+#endif
+#include <sys/syslog.h>
+
 
 int
@@ -877,5 +882,7 @@
   }
   unlock_exception_lock_in_handler(tcr);
+#ifndef DARWIN_USE_PSEUDO_SIGRETURN
   exit_signal_handler(tcr, old_valence);
+#endif
   /* raise_pending_interrupt(tcr); */
 #ifdef DARWIN_GS_HACK
@@ -884,5 +891,7 @@
   }
 #endif
+#ifndef DARWIN_USE_PSEUDO_SIGRETURN
   SIGRETURN(context);
+#endif
 }
 
@@ -1058,5 +1067,15 @@
 	  int old_valence;
           signed_natural alloc_displacement = 0;
-	  
+          LispObj 
+            *next_tsp = tcr->next_tsp,
+            *save_tsp = tcr->save_tsp,
+            *p,
+            q;
+            
+          if (next_tsp != save_tsp) {
+            tcr->next_tsp = save_tsp;
+          } else {
+            next_tsp = NULL;
+          }
 	  pc_luser_xp(context, tcr, &alloc_displacement);
 	  old_valence = prepare_to_wait_for_exception_lock(tcr, context);
@@ -1065,4 +1084,13 @@
           if (alloc_displacement) {
             tcr->save_allocptr -= alloc_displacement;
+          }
+          if (next_tsp) {
+            tcr->next_tsp = next_tsp;
+            p = next_tsp;
+            while (p != save_tsp) {
+              *p++ = 0;
+            }
+            q = (LispObj)save_tsp;
+            *next_tsp = q;
           }
 	  unlock_exception_lock_in_handler(tcr);
@@ -1217,4 +1245,73 @@
 
 void
+quit_handler(int signum, siginfo_t info, ExceptionInformation *xp)
+{
+  TCR *tcr = get_tcr(false);
+  area *a;
+  sigset_t mask;
+  
+  sigemptyset(&mask);
+
+
+  if (tcr) {
+    tcr->valence = TCR_STATE_FOREIGN;
+    a = tcr->vs_area;
+    if (a) {
+      a->active = a->high;
+    }
+    a = tcr->ts_area;
+    if (a) {
+      a->active = a->high;
+    }
+    a = tcr->cs_area;
+    if (a) {
+      a->active = a->high;
+    }
+  }
+  
+  pthread_sigmask(SIG_SETMASK,&mask,NULL);
+  pthread_exit(NULL);
+}
+
+void
+altstack_quit_handler(int signum, siginfo_t *info, ExceptionInformation *context)
+{
+#ifdef DARWIN_GS_HACK
+  Boolean gs_was_tcr = ensure_gs_pthread();
+#endif
+  TCR* tcr = get_tcr(true);
+  LispObj *foreign_rsp = find_foreign_rsp(xpGPR(context,Isp), tcr->cs_area, tcr);
+#ifdef LINUX
+  fpregset_t fpregs = NULL;
+#else
+  void *fpregs = NULL;
+#endif
+#ifdef DARWIN
+  MCONTEXT_T mcontextp = NULL;
+#endif
+
+  siginfo_t *info_copy = NULL;
+  ExceptionInformation *xp = NULL;
+
+  if (foreign_rsp) {
+#ifdef LINUX
+    foreign_rsp = copy_fpregs(context, foreign_rsp, &fpregs);
+#endif
+#ifdef DARWIN
+    foreign_rsp = copy_darwin_mcontext(UC_MCONTEXT(context), foreign_rsp, &mcontextp);
+#endif
+    foreign_rsp = copy_siginfo(info, foreign_rsp);
+    info_copy = (siginfo_t *)foreign_rsp;
+    foreign_rsp = copy_ucontext(context, foreign_rsp, fpregs);
+    xp = (ExceptionInformation *)foreign_rsp;
+#ifdef DARWIN
+    UC_MCONTEXT(xp) = mcontextp;
+#endif
+    *--foreign_rsp = (LispObj)__builtin_return_address(0);
+    switch_to_foreign_stack(foreign_rsp,quit_handler,signum,info_copy,xp);
+  }
+}
+
+void
 thread_signal_setup()
 {
@@ -1224,4 +1321,5 @@
   install_signal_handler(thread_suspend_signal, (void *)altstack_suspend_resume_handler);
   install_signal_handler(thread_resume_signal, (void *)altstack_suspend_resume_handler);
+  install_signal_handler(SIGQUIT, (void *)altstack_quit_handler);
 }
 
@@ -1523,4 +1621,6 @@
    function returned */
 
+TCR *gc_tcr = NULL;
+
 int
 gc_like_from_xp(ExceptionInformation *xp, 
@@ -1542,4 +1642,6 @@
     return 0;
   }
+
+  gc_tcr = tcr;
 
   /* This is generally necessary if the current thread invoked the GC
@@ -1577,4 +1679,6 @@
     other_tcr = other_tcr->next;
   } while (other_tcr != tcr);
+
+  gc_tcr = NULL;
 
   resume_other_threads(true);
@@ -2008,4 +2112,10 @@
 #else
 #define ts_pc(t) t.eip
+#endif
+
+#ifdef DARWIN_USE_PSEUDO_SIGRETURN
+#define DARWIN_EXCEPTION_HANDLER signal_handler
+#else
+#define DARWIN_EXCEPTION_HANDLER pseudo_signal_handler
 #endif
 
@@ -2088,5 +2198,5 @@
       if (signum) {
         kret = setup_signal_frame(thread,
-                                  (void *)pseudo_signal_handler,
+                                  (void *)DARWIN_EXCEPTION_HANDLER,
                                   signum,
                                   code,
@@ -2107,8 +2217,17 @@
   } else {
     SET_TCR_FLAG(tcr,TCR_FLAG_BIT_PENDING_EXCEPTION);
+      
 #if 0
     fprintf(stderr, "deferring pending exception in 0x%x\n", tcr);
 #endif
     kret = 0;
+    if (tcr == gc_tcr) {
+      int i;
+      write(1, "exception in GC thread. Sleeping for 60 seconds\n",sizeof("exception in GC thread.  Sleeping for 60 seconds\n"));
+      for (i = 0; i < 60; i++) {
+        sleep(1);
+      }
+      _exit(EX_SOFTWARE);
+    }
   }
   return kret;
@@ -2117,4 +2236,6 @@
 
 
+
+static mach_port_t mach_exception_thread = (mach_port_t)0;
 
 
@@ -2129,4 +2250,5 @@
   mach_port_t p = TCR_TO_EXCEPTION_PORT(arg);
 
+  mach_exception_thread = pthread_mach_thread_np(pthread_self());
   mach_msg_server(exc_server, 256, p, 0);
   /* Should never return. */
@@ -2134,4 +2256,17 @@
 }
 
+
+
+void
+mach_exception_thread_shutdown()
+{
+  kern_return_t kret;
+
+  fprintf(stderr, "terminating Mach exception thread, 'cause exit can't\n");
+  kret = thread_terminate(mach_exception_thread);
+  if (kret != KERN_SUCCESS) {
+    fprintf(stderr, "Couldn't terminate exception thread, kret = %d\n",kret);
+  }
+}
 
 
