ENH: Added GetExceptionString method to provide an error description when GetState returns Exception.
This commit is contained in:
parent
f48941f261
commit
1c8f885f9d
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue