diff --git a/Process.h.in b/Process.h.in
index 7b77bb9f6b5dc912d5430fd846dc1d33f678628b..27a5b6e7e4495de847ffb8c876365395fc398043 100644
--- a/Process.h.in
+++ b/Process.h.in
@@ -56,6 +56,7 @@
 #define kwsysProcess_GetExitCode         kwsys(Process_GetExitCode)
 #define kwsysProcess_GetExitValue        kwsys(Process_GetExitValue)
 #define kwsysProcess_GetErrorString      kwsys(Process_GetErrorString)
+#define kwsysProcess_GetExceptionString  kwsys(Process_GetExceptionString)
 #define kwsysProcess_Execute             kwsys(Process_Execute)
 #define kwsysProcess_WaitForData         kwsys(Process_WaitForData)
 #define kwsysProcess_Pipes_e             kwsys(Process_Pipes_e)
@@ -224,6 +225,12 @@ kwsysEXPORT int kwsysProcess_GetExitValue(kwsysProcess* cp);
  */
 kwsysEXPORT const char* kwsysProcess_GetErrorString(kwsysProcess* cp);
 
+/**
+ * When GetState returns "Exception", this method returns a string
+ * describing the problem.  Otherwise, it returns NULL.
+ */
+kwsysEXPORT const char* kwsysProcess_GetExceptionString(kwsysProcess* cp);
+
 /**
  * Start executing the child process.
  */
@@ -335,6 +342,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
 # undef kwsysProcess_GetExitCode
 # undef kwsysProcess_GetExitValue
 # undef kwsysProcess_GetErrorString
+# undef kwsysProcess_GetExceptionString
 # undef kwsysProcess_Execute
 # undef kwsysProcess_WaitForData
 # undef kwsysProcess_Pipes_e
diff --git a/ProcessUNIX.c b/ProcessUNIX.c
index 59b966118a4aa9e5676e37086df6cf648f5b2aa2..c9f6315ef79d10e348df6c6c0a8273b90b849403 100644
--- a/ProcessUNIX.c
+++ b/ProcessUNIX.c
@@ -95,6 +95,7 @@ static kwsysProcessTime kwsysProcessTimeFromDouble(double d);
 static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2);
 static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2);
 static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2);
+static void kwsysProcessSetExitException(kwsysProcess* cp, int sig);
 static void kwsysProcessChildErrorExit(int errorPipe);
 static void kwsysProcessRestoreDefaultSignalHandlers();
 
@@ -161,6 +162,9 @@ struct kwsysProcess_s
   /* Buffer for error message in case of failure.  */
   char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1];
 
+  /* Description for the ExitException.  */
+  char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE+1];
+
   /* The exit codes of each child process in the pipeline.  */
   int* CommandExitCodes;
 
@@ -481,13 +485,27 @@ const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
 {
   if(!cp)
     {
-    return "Process management structure could not be allocated.";
+    return "Process management structure could not be allocated";
     }
   else if(cp->State == kwsysProcess_State_Error)
     {
     return cp->ErrorMessage;
     }
-  return 0;
+  return "Success";
+}
+
+/*--------------------------------------------------------------------------*/
+const char* kwsysProcess_GetExceptionString(kwsysProcess* cp)
+{
+  if(!cp)
+    {
+    return "GetExceptionString called with NULL process management structure";
+    }
+  else if(cp->State == kwsysProcess_State_Exception)
+    {
+    return cp->ExitExceptionString;
+    }
+  return "No exception";
 }
 
 /*--------------------------------------------------------------------------*/
@@ -941,26 +959,8 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
     {
     /* The child received an unhandled signal.  */
     cp->State = kwsysProcess_State_Exception;
-    switch ((int)WTERMSIG(status))
-      {
-#ifdef SIGSEGV
-      case SIGSEGV: cp->ExitException = kwsysProcess_Exception_Fault; break;
-#endif
-#ifdef SIGBUS
-      case SIGBUS: cp->ExitException = kwsysProcess_Exception_Fault; break;
-#endif
-#ifdef SIGFPE
-      case SIGFPE:  cp->ExitException = kwsysProcess_Exception_Numerical; break;
-#endif
-#ifdef SIGILL
-      case SIGILL:  cp->ExitException = kwsysProcess_Exception_Illegal; break;
-#endif
-#ifdef SIGINT
-      case SIGINT:  cp->ExitException = kwsysProcess_Exception_Interrupt; break;
-#endif
-      default: cp->ExitException = kwsysProcess_Exception_Other; break;
-      }
     cp->ExitCode = status;
+    kwsysProcessSetExitException(cp, (int)WTERMSIG(status));
     }
   else
     {
@@ -1019,6 +1019,7 @@ static int kwsysProcessInitialize(kwsysProcess* cp)
   cp->ExitCode = 1;
   cp->ExitValue = 1;
   cp->ErrorMessage[0] = 0;
+  strcpy(cp->ExitExceptionString, "No exception");
 
   if(cp->ForkPIDs)
     {
@@ -1461,6 +1462,132 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProc
   return out;
 }
 
+/*--------------------------------------------------------------------------*/
+#define KWSYSPE_CASE(type, str) \
+  cp->ExitException = kwsysProcess_Exception_##type; \
+  strcpy(cp->ExitExceptionString, str)
+static void kwsysProcessSetExitException(kwsysProcess* cp, int sig)
+{
+  switch (sig)
+    {
+#ifdef SIGSEGV
+    case SIGSEGV: KWSYSPE_CASE(Fault, "Segmentation fault"); break;
+#endif
+#ifdef SIGBUS
+    case SIGBUS: KWSYSPE_CASE(Fault, "Bus error"); break;
+#endif
+#ifdef SIGFPE
+    case SIGFPE: KWSYSPE_CASE(Numerical, "Floating-point exception"); break;
+#endif
+#ifdef SIGILL
+    case SIGILL: KWSYSPE_CASE(Illegal, "Illegal instruction"); break;
+#endif
+#ifdef SIGINT
+    case SIGINT: KWSYSPE_CASE(Interrupt, "User interrupt"); break;
+#endif
+#ifdef SIGABRT
+    case SIGABRT: KWSYSPE_CASE(Other, "Child aborted"); break;
+#endif
+#ifdef SIGKILL
+    case SIGKILL: KWSYSPE_CASE(Other, "Child killed"); break;
+#endif
+#ifdef SIGTERM
+    case SIGTERM: KWSYSPE_CASE(Other, "Child terminated"); break;
+#endif
+#ifdef SIGHUP
+    case SIGHUP: KWSYSPE_CASE(Other, "SIGHUP"); break;
+#endif
+#ifdef SIGQUIT
+    case SIGQUIT: KWSYSPE_CASE(Other, "SIGQUIT"); break;
+#endif
+#ifdef SIGTRAP
+    case SIGTRAP: KWSYSPE_CASE(Other, "SIGTRAP"); break;
+#endif
+#ifdef SIGIOT
+# if !defined(SIGABRT) || SIGIOT != SIGABRT
+    case SIGIOT: KWSYSPE_CASE(Other, "SIGIOT"); break;
+# endif
+#endif
+#ifdef SIGUSR1
+    case SIGUSR1: KWSYSPE_CASE(Other, "SIGUSR1"); break;
+#endif
+#ifdef SIGUSR2
+    case SIGUSR2: KWSYSPE_CASE(Other, "SIGUSR2"); break;
+#endif
+#ifdef SIGPIPE
+    case SIGPIPE: KWSYSPE_CASE(Other, "SIGPIPE"); break;
+#endif
+#ifdef SIGALRM
+    case SIGALRM: KWSYSPE_CASE(Other, "SIGALRM"); break;
+#endif
+#ifdef SIGSTKFLT
+    case SIGSTKFLT: KWSYSPE_CASE(Other, "SIGSTKFLT"); break;
+#endif
+#ifdef SIGCHLD
+    case SIGCHLD: KWSYSPE_CASE(Other, "SIGCHLD"); break;
+#elif defined(SIGCLD)
+    case SIGCLD: KWSYSPE_CASE(Other, "SIGCLD"); break;
+#endif
+#ifdef SIGCONT
+    case SIGCONT: KWSYSPE_CASE(Other, "SIGCONT"); break;
+#endif
+#ifdef SIGSTOP
+    case SIGSTOP: KWSYSPE_CASE(Other, "SIGSTOP"); break;
+#endif
+#ifdef SIGTSTP
+    case SIGTSTP: KWSYSPE_CASE(Other, "SIGTSTP"); break;
+#endif
+#ifdef SIGTTIN
+    case SIGTTIN: KWSYSPE_CASE(Other, "SIGTTIN"); break;
+#endif
+#ifdef SIGTTOU
+    case SIGTTOU: KWSYSPE_CASE(Other, "SIGTTOU"); break;
+#endif
+#ifdef SIGURG
+    case SIGURG: KWSYSPE_CASE(Other, "SIGURG"); break;
+#endif
+#ifdef SIGXCPU
+    case SIGXCPU: KWSYSPE_CASE(Other, "SIGXCPU"); break;
+#endif
+#ifdef SIGXFSZ
+    case SIGXFSZ: KWSYSPE_CASE(Other, "SIGXFSZ"); break;
+#endif
+#ifdef SIGVTALRM
+    case SIGVTALRM: KWSYSPE_CASE(Other, "SIGVTALRM"); break;
+#endif
+#ifdef SIGPROF
+    case SIGPROF: KWSYSPE_CASE(Other, "SIGPROF"); break;
+#endif
+#ifdef SIGWINCH
+    case SIGWINCH: KWSYSPE_CASE(Other, "SIGWINCH"); break;
+#endif
+#ifdef SIGPOLL
+    case SIGPOLL: KWSYSPE_CASE(Other, "SIGPOLL"); break;
+#endif
+#ifdef SIGIO
+# if !defined(SIGPOLL) || SIGIO != SIGPOLL
+    case SIGIO: KWSYSPE_CASE(Other, "SIGIO"); break;
+# endif
+#endif
+#ifdef SIGPWR
+    case SIGPWR: KWSYSPE_CASE(Other, "SIGPWR"); break;
+#endif
+#ifdef SIGSYS
+    case SIGSYS: KWSYSPE_CASE(Other, "SIGSYS"); break;
+#endif
+#ifdef SIGUNUSED
+# if !defined(SIGSYS) || SIGUNUSED != SIGSYS
+    case SIGUNUSED: KWSYSPE_CASE(Other, "SIGUNUSED"); break;
+# endif
+#endif
+    default:
+      cp->ExitException = kwsysProcess_Exception_Other;
+      sprintf(cp->ExitExceptionString, "Signal %d", sig);
+      break;
+    }
+}
+#undef KWSYSPE_CASE
+
 /*--------------------------------------------------------------------------*/
 /* When the child process encounters an error before its program is
    invoked, this is called to report the error to the parent and
diff --git a/ProcessWin32.c b/ProcessWin32.c
index 964a544282a9eff8f61dcd5566c20619a5082b62..4de4bad5c6972b94ad1f51f0e8e0517ccc1305a5 100644
--- a/ProcessWin32.c
+++ b/ProcessWin32.c
@@ -92,6 +92,7 @@ static kwsysProcessTime kwsysProcessTimeFromDouble(double d);
 static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2);
 static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2);
 static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2);
+static void kwsysProcessSetExitException(kwsysProcess* cp, int code);
 extern kwsysEXPORT int kwsysEncodedWriteArrayProcessFwd9x(const char* fname);
 
 /*--------------------------------------------------------------------------*/
@@ -234,6 +235,9 @@ struct kwsysProcess_s
   /* Buffer for error messages (possibly from Win9x child).  */
   char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1];
 
+  /* Description for the ExitException.  */
+  char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE+1];
+
   /* Windows process information data.  */
   PROCESS_INFORMATION* ProcessInformation;
 
@@ -905,13 +909,27 @@ const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
 {
   if(!cp)
     {
-    return "Process management structure could not be allocated.";
+    return "Process management structure could not be allocated";
     }
   else if(cp->State == kwsysProcess_State_Error)
     {
     return cp->ErrorMessage;
     }
-  return 0;
+  return "Success";
+}
+
+/*--------------------------------------------------------------------------*/
+const char* kwsysProcess_GetExceptionString(kwsysProcess* cp)
+{
+  if(!cp)
+    {
+    return "GetExceptionString called with NULL process management structure";
+    }
+  else if(cp->State == kwsysProcess_State_Exception)
+    {
+    return cp->ExitExceptionString;
+    }
+  return "No exception";
 }
 
 /*--------------------------------------------------------------------------*/
@@ -1312,39 +1330,8 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
       {
       /* Child terminated due to exceptional behavior.  */
       cp->State = kwsysProcess_State_Exception;
-      switch (cp->ExitCode)
-        {
-        case CONTROL_C_EXIT:
-          cp->ExitException = kwsysProcess_Exception_Interrupt; break;
-
-        case EXCEPTION_FLT_DENORMAL_OPERAND:
-        case EXCEPTION_FLT_DIVIDE_BY_ZERO:
-        case EXCEPTION_FLT_INEXACT_RESULT:
-        case EXCEPTION_FLT_INVALID_OPERATION:
-        case EXCEPTION_FLT_OVERFLOW:
-        case EXCEPTION_FLT_STACK_CHECK:
-        case EXCEPTION_FLT_UNDERFLOW:
-        case EXCEPTION_INT_DIVIDE_BY_ZERO:
-        case EXCEPTION_INT_OVERFLOW:
-          cp->ExitException = kwsysProcess_Exception_Numerical; break;
-
-        case EXCEPTION_ACCESS_VIOLATION:
-        case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
-        case EXCEPTION_DATATYPE_MISALIGNMENT:
-        case EXCEPTION_INVALID_DISPOSITION:
-        case EXCEPTION_IN_PAGE_ERROR:
-        case EXCEPTION_NONCONTINUABLE_EXCEPTION:
-        case EXCEPTION_STACK_OVERFLOW:
-          cp->ExitException = kwsysProcess_Exception_Fault; break;
-
-        case EXCEPTION_ILLEGAL_INSTRUCTION:
-        case EXCEPTION_PRIV_INSTRUCTION:
-          cp->ExitException = kwsysProcess_Exception_Illegal; break;
-
-        default:
-          cp->ExitException = kwsysProcess_Exception_Other; break;
-        }
       cp->ExitValue = 1;
+      kwsysProcessSetExitException(cp, cp->ExitCode);
       }
     else
       {
@@ -1493,6 +1480,7 @@ int kwsysProcessInitialize(kwsysProcess* cp)
 
   /* Reset error data.  */
   cp->ErrorMessage[0] = 0;
+  strcpy(cp->ExitExceptionString, "No exception");
 
   /* Allocate process information for each process.  */
   cp->ProcessInformation =
@@ -2070,3 +2058,73 @@ kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime
   out.QuadPart = in1.QuadPart - in2.QuadPart;
   return out;
 }
+
+/*--------------------------------------------------------------------------*/
+#define KWSYSPE_CASE(type, str) \
+  cp->ExitException = kwsysProcess_Exception_##type; \
+  strcpy(cp->ExitExceptionString, str)
+static void kwsysProcessSetExitException(kwsysProcess* cp, int code)
+{
+  switch (code)
+    {
+    case STATUS_CONTROL_C_EXIT:
+      KWSYSPE_CASE(Interrupt, "User interrupt"); break;
+
+    case STATUS_FLOAT_DENORMAL_OPERAND:
+      KWSYSPE_CASE(Numerical, "Floating-point exception (denormal operand)"); break;
+    case STATUS_FLOAT_DIVIDE_BY_ZERO:
+      KWSYSPE_CASE(Numerical, "Divide-by-zero"); break;
+    case STATUS_FLOAT_INEXACT_RESULT:
+      KWSYSPE_CASE(Numerical, "Floating-point exception (inexact result)"); break;
+    case STATUS_FLOAT_INVALID_OPERATION:
+      KWSYSPE_CASE(Numerical, "Invalid floating-point operation"); break;
+    case STATUS_FLOAT_OVERFLOW:
+      KWSYSPE_CASE(Numerical, "Floating-point overflow"); break;
+    case STATUS_FLOAT_STACK_CHECK:
+      KWSYSPE_CASE(Numerical, "Floating-point stack check failed"); break;
+    case STATUS_FLOAT_UNDERFLOW:
+      KWSYSPE_CASE(Numerical, "Floating-point underflow"); break;
+#ifdef STATUS_FLOAT_MULTIPLE_FAULTS
+    case STATUS_FLOAT_MULTIPLE_FAULTS:
+      KWSYSPE_CASE(Numerical, "Floating-point exception (multiple faults)"); break;
+#endif
+#ifdef STATUS_FLOAT_MULTIPLE_TRAPS
+    case STATUS_FLOAT_MULTIPLE_TRAPS:
+      KWSYSPE_CASE(Numerical, "Floating-point exception (multiple traps)"); break;
+#endif
+    case STATUS_INTEGER_DIVIDE_BY_ZERO:
+      KWSYSPE_CASE(Numerical, "Integer divide-by-zero"); break;
+    case STATUS_INTEGER_OVERFLOW:
+      KWSYSPE_CASE(Numerical, "Integer overflow"); break;
+
+    case STATUS_DATATYPE_MISALIGNMENT:
+      KWSYSPE_CASE(Fault, "Datatype misalignment"); break;
+    case STATUS_ACCESS_VIOLATION:
+      KWSYSPE_CASE(Fault, "Access violation"); break;
+    case STATUS_IN_PAGE_ERROR:
+      KWSYSPE_CASE(Fault, "In-page error"); break;
+    case STATUS_INVALID_HANDLE:
+      KWSYSPE_CASE(Fault, "Invalid hanlde"); break;
+    case STATUS_NONCONTINUABLE_EXCEPTION:
+      KWSYSPE_CASE(Fault, "Noncontinuable exception"); break;
+    case STATUS_INVALID_DISPOSITION:
+      KWSYSPE_CASE(Fault, "Invalid disposition"); break;
+    case STATUS_ARRAY_BOUNDS_EXCEEDED:
+      KWSYSPE_CASE(Fault, "Array bounds exceeded"); break;
+    case STATUS_STACK_OVERFLOW:
+      KWSYSPE_CASE(Fault, "Stack overflow"); break;
+
+    case STATUS_ILLEGAL_INSTRUCTION:
+      KWSYSPE_CASE(Illegal, "Illegal instruction"); break;
+    case STATUS_PRIVILEGED_INSTRUCTION:
+      KWSYSPE_CASE(Illegal, "Privileged instruction"); break;
+
+    case STATUS_NO_MEMORY:
+    default:
+      cp->ExitException = kwsysProcess_Exception_Other;
+      sprintf(cp->ExitExceptionString, "Exit code 0x%x\n", code);
+      break;
+    }
+}
+#undef KWSYSPE_CASE
+
diff --git a/test1.cxx b/test1.cxx
index 1486f0c246755b6fb4e53eac0a113adceab22c93..183ea8618cbd77c265b77c301db0df3b378a51b4 100644
--- a/test1.cxx
+++ b/test1.cxx
@@ -28,6 +28,15 @@ int main()
     {
     kwsys_ios::cout.write(data, length);
     }
+  kwsysProcess_WaitForExit(kp, 0);
+  if(kwsysProcess_GetState(kp) == kwsysProcess_State_Error)
+    {
+    kwsys_ios::cout << kwsysProcess_GetErrorString(kp) << kwsys_ios::endl;
+    }
+  else if(kwsysProcess_GetState(kp) == kwsysProcess_State_Exception)
+    {
+    kwsys_ios::cout << kwsysProcess_GetExceptionString(kp) << kwsys_ios::endl;
+    }
   kwsysProcess_Delete(kp);
   kwsys_ios::cout << kwsys_ios::endl;
   return 0;