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

This commit is contained in:
Brad King 2003-12-30 16:23:16 -05:00
parent f48941f261
commit 1c8f885f9d
4 changed files with 257 additions and 55 deletions

View File

@ -56,6 +56,7 @@
#define kwsysProcess_GetExitCode kwsys(Process_GetExitCode) #define kwsysProcess_GetExitCode kwsys(Process_GetExitCode)
#define kwsysProcess_GetExitValue kwsys(Process_GetExitValue) #define kwsysProcess_GetExitValue kwsys(Process_GetExitValue)
#define kwsysProcess_GetErrorString kwsys(Process_GetErrorString) #define kwsysProcess_GetErrorString kwsys(Process_GetErrorString)
#define kwsysProcess_GetExceptionString kwsys(Process_GetExceptionString)
#define kwsysProcess_Execute kwsys(Process_Execute) #define kwsysProcess_Execute kwsys(Process_Execute)
#define kwsysProcess_WaitForData kwsys(Process_WaitForData) #define kwsysProcess_WaitForData kwsys(Process_WaitForData)
#define kwsysProcess_Pipes_e kwsys(Process_Pipes_e) #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); 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. * Start executing the child process.
*/ */
@ -335,6 +342,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
# undef kwsysProcess_GetExitCode # undef kwsysProcess_GetExitCode
# undef kwsysProcess_GetExitValue # undef kwsysProcess_GetExitValue
# undef kwsysProcess_GetErrorString # undef kwsysProcess_GetErrorString
# undef kwsysProcess_GetExceptionString
# undef kwsysProcess_Execute # undef kwsysProcess_Execute
# undef kwsysProcess_WaitForData # undef kwsysProcess_WaitForData
# undef kwsysProcess_Pipes_e # undef kwsysProcess_Pipes_e

View File

@ -95,6 +95,7 @@ static kwsysProcessTime kwsysProcessTimeFromDouble(double d);
static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2); static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2);
static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2); static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2);
static kwsysProcessTime kwsysProcessTimeSubtract(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 kwsysProcessChildErrorExit(int errorPipe);
static void kwsysProcessRestoreDefaultSignalHandlers(); static void kwsysProcessRestoreDefaultSignalHandlers();
@ -161,6 +162,9 @@ struct kwsysProcess_s
/* Buffer for error message in case of failure. */ /* Buffer for error message in case of failure. */
char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1]; 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. */ /* The exit codes of each child process in the pipeline. */
int* CommandExitCodes; int* CommandExitCodes;
@ -481,13 +485,27 @@ const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
{ {
if(!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) else if(cp->State == kwsysProcess_State_Error)
{ {
return cp->ErrorMessage; 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. */ /* The child received an unhandled signal. */
cp->State = kwsysProcess_State_Exception; 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; cp->ExitCode = status;
kwsysProcessSetExitException(cp, (int)WTERMSIG(status));
} }
else else
{ {
@ -1019,6 +1019,7 @@ static int kwsysProcessInitialize(kwsysProcess* cp)
cp->ExitCode = 1; cp->ExitCode = 1;
cp->ExitValue = 1; cp->ExitValue = 1;
cp->ErrorMessage[0] = 0; cp->ErrorMessage[0] = 0;
strcpy(cp->ExitExceptionString, "No exception");
if(cp->ForkPIDs) if(cp->ForkPIDs)
{ {
@ -1461,6 +1462,132 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProc
return out; 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 /* When the child process encounters an error before its program is
invoked, this is called to report the error to the parent and invoked, this is called to report the error to the parent and

View File

@ -92,6 +92,7 @@ static kwsysProcessTime kwsysProcessTimeFromDouble(double d);
static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2); static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2);
static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2); static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2);
static kwsysProcessTime kwsysProcessTimeSubtract(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); extern kwsysEXPORT int kwsysEncodedWriteArrayProcessFwd9x(const char* fname);
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@ -234,6 +235,9 @@ struct kwsysProcess_s
/* Buffer for error messages (possibly from Win9x child). */ /* Buffer for error messages (possibly from Win9x child). */
char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1]; char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1];
/* Description for the ExitException. */
char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE+1];
/* Windows process information data. */ /* Windows process information data. */
PROCESS_INFORMATION* ProcessInformation; PROCESS_INFORMATION* ProcessInformation;
@ -905,13 +909,27 @@ const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
{ {
if(!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) else if(cp->State == kwsysProcess_State_Error)
{ {
return cp->ErrorMessage; 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. */ /* Child terminated due to exceptional behavior. */
cp->State = kwsysProcess_State_Exception; 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; cp->ExitValue = 1;
kwsysProcessSetExitException(cp, cp->ExitCode);
} }
else else
{ {
@ -1493,6 +1480,7 @@ int kwsysProcessInitialize(kwsysProcess* cp)
/* Reset error data. */ /* Reset error data. */
cp->ErrorMessage[0] = 0; cp->ErrorMessage[0] = 0;
strcpy(cp->ExitExceptionString, "No exception");
/* Allocate process information for each process. */ /* Allocate process information for each process. */
cp->ProcessInformation = cp->ProcessInformation =
@ -2070,3 +2058,73 @@ kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime
out.QuadPart = in1.QuadPart - in2.QuadPart; out.QuadPart = in1.QuadPart - in2.QuadPart;
return out; 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

View File

@ -28,6 +28,15 @@ int main()
{ {
kwsys_ios::cout.write(data, length); 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); kwsysProcess_Delete(kp);
kwsys_ios::cout << kwsys_ios::endl; kwsys_ios::cout << kwsys_ios::endl;
return 0; return 0;