Bugfix: Perform proper process shutdown on 'quit' and error.

diff --git a/debugger/dbg.y b/debugger/dbg.y
index f16686f..2742108 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -123,7 +123,7 @@
     | error tEOL               { yyerrok; }
 
 command:
-      tQUIT tEOL               { exit(0); }
+      tQUIT tEOL               { DEBUG_Exit(0); }
     | tHELP tEOL               { DEBUG_Help(); }
     | tHELP tINFO tEOL         { DEBUG_HelpInfo(); }
     | tCONT tEOL               { dbg_exec_count = 1; 
@@ -431,6 +431,41 @@
     else fprintf(stderr,"Invalid mode (use 16 or 32)\n");
 }
 
+/***********************************************************************
+ *           DEBUG_Freeze
+ */
+static void DEBUG_Freeze( BOOL freeze )
+{
+    static BOOL frozen = FALSE;
+
+    if ( freeze && !frozen )
+    {
+        /* Don't freeze thread currently holding the X crst! */
+        EnterCriticalSection( &X11DRV_CritSection );
+        CLIENT_DebuggerRequest( DEBUGGER_FREEZE_ALL );
+        LeaveCriticalSection( &X11DRV_CritSection );
+        frozen = TRUE;
+    }
+
+    if ( !freeze && frozen )
+    {
+        CLIENT_DebuggerRequest( DEBUGGER_UNFREEZE_ALL );
+        frozen = FALSE;
+    }
+}
+
+/***********************************************************************
+ *           DEBUG_Exit
+ *
+ * Kill current process.
+ */
+void DEBUG_Exit( DWORD exit_code )
+{
+    DEBUG_Freeze( FALSE );
+
+    TASK_KillTask( 0 );  /* FIXME: should not be necessary */
+    TerminateProcess( GetCurrentProcess(), exit_code );
+}
 
 /***********************************************************************
  *           DEBUG_Main
@@ -440,7 +475,6 @@
 static void DEBUG_Main( BOOL is_debug )
 {
     static int loaded_symbols = 0;
-    static BOOL frozen = FALSE;
     static BOOL in_debugger = FALSE;
     char SymbolTableFile[256];
     int newmode;
@@ -452,7 +486,7 @@
     if (in_debugger)
     {
         fprintf( stderr, " inside debugger, exiting.\n" );
-        exit(1);
+        DEBUG_Exit(1);
     }
     in_debugger = TRUE;
     yyin = stdin;
@@ -472,14 +506,7 @@
     {
         loaded_symbols++;
 
-        if ( !frozen )
-        {
-            /* Don't freeze thread currently holding the X crst! */
-            EnterCriticalSection( &X11DRV_CritSection );
-            CLIENT_DebuggerRequest( DEBUGGER_FREEZE_ALL );
-            LeaveCriticalSection( &X11DRV_CritSection );
-            frozen = TRUE;
-        }
+        DEBUG_Freeze( TRUE );
 
 #ifdef DBG_need_heap
 	/*
@@ -540,14 +567,7 @@
 
         GlobalUnlock16( GetCurrentTask() );
 
-        if ( !frozen )
-        {
-            /* Don't freeze thread currently holding the X crst! */
-            EnterCriticalSection( &X11DRV_CritSection );
-            CLIENT_DebuggerRequest( DEBUGGER_FREEZE_ALL );
-            LeaveCriticalSection( &X11DRV_CritSection );
-            frozen = TRUE;
-        }
+        DEBUG_Freeze( TRUE );
 
         /* Put the display in a correct state */
 	USER_Driver->pBeginDebugging();
@@ -619,11 +639,7 @@
       {
 	dbg_exec_count = 0;
 
-        if ( frozen )
-        {
-            CLIENT_DebuggerRequest( DEBUGGER_UNFREEZE_ALL );
-            frozen = FALSE;
-        }
+        DEBUG_Freeze( FALSE );
       }
 
     in_debugger = FALSE;
@@ -645,7 +661,7 @@
         is_debug = TRUE;
         break;
     case CONTROL_C_EXIT:
-        if (!Options.debug) exit(0);
+        if (!Options.debug) DEBUG_Exit(0);
         break;
     }
 
diff --git a/debugger/debug.l b/debugger/debug.l
index 02aa298..045ec39 100644
--- a/debugger/debug.l
+++ b/debugger/debug.l
@@ -239,7 +239,7 @@
         if (!line)
         {
             fprintf( stderr, "\n" );
-            exit(0);
+            DEBUG_Exit(0);
         }
 
         /* Remove leading and trailing whitespace from the line */
@@ -264,7 +264,7 @@
             if (size < len + 1)
             {
                 fprintf(stderr,"Fatal readline goof.\n");
-                exit(0);
+                DEBUG_Exit(0);
             }
             strcpy(buf, line);
             buf[len] = '\n';
diff --git a/debugger/expr.c b/debugger/expr.c
index d8e623a..12567f1 100644
--- a/debugger/expr.c
+++ b/debugger/expr.c
@@ -634,7 +634,7 @@
       break;
     default:
       fprintf(stderr,"Unexpected expression.\n");
-      exit(123);
+      DEBUG_Exit(123);
       break;
     }
 
@@ -794,7 +794,7 @@
       break;
     default:
       fprintf(stderr,"Unexpected expression.\n");
-      exit(123);
+      DEBUG_Exit(123);
       break;
     }
 
@@ -855,7 +855,7 @@
       break;
     default:
       fprintf(stderr,"Unexpected expression.\n");
-      exit(123);
+      DEBUG_Exit(123);
       break;
     }
 
@@ -912,7 +912,7 @@
       break;
     default:
       fprintf(stderr,"Unexpected expression.\n");
-      exit(123);
+      DEBUG_Exit(123);
       break;
     }
 
diff --git a/include/debugger.h b/include/debugger.h
index bcbded2..2fa3f0f 100644
--- a/include/debugger.h
+++ b/include/debugger.h
@@ -317,6 +317,7 @@
 
   /* debugger/dbg.y */
 extern DWORD wine_debugger( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance );
+extern void DEBUG_Exit( DWORD exit_code );
 
   /* Choose your allocator! */
 #if 1