Commit 54ea17ae authored by Brad King's avatar Brad King

ENH: Added GetExceptionString method to provide an error description when...

ENH: Added GetExceptionString method to provide an error description when GetState returns Exception.
parent 1c768561
......@@ -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
......
......@@ -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
......
......@@ -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
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment