From b7eba998e6d30b5d3482f0cce4b1ce8cb82de330 Mon Sep 17 00:00:00 2001 From: Adam Weisi <adam.weisi@intel.com> Date: Fri, 5 May 2017 18:22:23 +0200 Subject: [PATCH] Process: Add APIs to get results of individual processes When running a pipeline of child processes, provide clients a way to get individual results. --- Process.h.in | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ ProcessUNIX.c | 48 ++++++++++++++++++++++++++++++++--- ProcessWin32.c | 49 ++++++++++++++++++++++++++++++++--- 3 files changed, 160 insertions(+), 6 deletions(-) diff --git a/Process.h.in b/Process.h.in index 6268feb..237001c 100644 --- a/Process.h.in +++ b/Process.h.in @@ -56,6 +56,14 @@ #define kwsysProcess_GetExitValue kwsys_ns(Process_GetExitValue) #define kwsysProcess_GetErrorString kwsys_ns(Process_GetErrorString) #define kwsysProcess_GetExceptionString kwsys_ns(Process_GetExceptionString) +#define kwsysProcess_GetStateByIndex kwsys_ns(Process_GetStateByIndex) +#define kwsysProcess_GetExitExceptionByIndex \ + kwsys_ns(Process_GetExitExceptionByIndex) +#define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex) +#define kwsysProcess_GetExitValueByIndex kwsys_ns(Process_GetExitValueByIndex) +#define kwsysProcess_GetExceptionStringByIndex \ + kwsys_ns(Process_GetExceptionStringByIndex) +#define kwsysProcess_GetExitCodeByIndex kwsys_ns(Process_GetExitCodeByIndex) #define kwsysProcess_Execute kwsys_ns(Process_Execute) #define kwsysProcess_Disown kwsys_ns(Process_Disown) #define kwsysProcess_WaitForData kwsys_ns(Process_WaitForData) @@ -297,6 +305,67 @@ kwsysEXPORT const char* kwsysProcess_GetErrorString(kwsysProcess* cp); */ kwsysEXPORT const char* kwsysProcess_GetExceptionString(kwsysProcess* cp); +/** +* Get the current state of the Process instance. Possible states are: +* +* kwsysProcess_StateByIndex_Starting = Execute has not yet been called. +* kwsysProcess_StateByIndex_Exception = Child process exited abnormally. +* kwsysProcess_StateByIndex_Exited = Child process exited normally. +* kwsysProcess_StateByIndex_Error = Error getting the child return code. +*/ +kwsysEXPORT int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx); +enum kwsysProcess_StateByIndex_e +{ + kwsysProcess_StateByIndex_Starting = kwsysProcess_State_Starting, + kwsysProcess_StateByIndex_Exception = kwsysProcess_State_Exception, + kwsysProcess_StateByIndex_Exited = kwsysProcess_State_Exited, + kwsysProcess_StateByIndex_Error = kwsysProcess_State_Error +}; + +/** +* When GetState returns "Exception", this method returns a +* platform-independent description of the exceptional behavior that +* caused the child to terminate abnormally. Possible exceptions are: +* +* kwsysProcess_Exception_None = No exceptional behavior occurred. +* kwsysProcess_Exception_Fault = Child crashed with a memory fault. +* kwsysProcess_Exception_Illegal = Child crashed with an illegal +* instruction. +* kwsysProcess_Exception_Interrupt = Child was interrupted by user +* (Cntl-C/Break). +* kwsysProcess_Exception_Numerical = Child crashed with a numerical +* exception. +* kwsysProcess_Exception_Other = Child terminated for another reason. +*/ +kwsysEXPORT int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp, + int idx); + +/** +* When GetState returns "Exited" or "Exception", this method returns +* the platform-specific raw exit code of the process. UNIX platforms +* should use WIFEXITED/WEXITSTATUS and WIFSIGNALED/WTERMSIG to access +* this value. Windows users should compare the value to the various +* EXCEPTION_* values. +* +* If GetState returns "Exited", use GetExitValue to get the +* platform-independent child return value. +*/ +kwsysEXPORT int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx); + +/** +* When GetState returns "Exited", this method returns the child's +* platform-independent exit code (such as the value returned by the +* child's main). +*/ +kwsysEXPORT int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx); + +/** +* When GetState returns "Exception", this method returns a string +* describing the problem. Otherwise, it returns NULL. +*/ +kwsysEXPORT const char* kwsysProcess_GetExceptionStringByIndex( + kwsysProcess* cp, int idx); + /** * Start executing the child process. */ diff --git a/ProcessUNIX.c b/ProcessUNIX.c index 8bcb671..9ebcfce 100644 --- a/ProcessUNIX.c +++ b/ProcessUNIX.c @@ -703,6 +703,48 @@ const char* kwsysProcess_GetExceptionString(kwsysProcess* cp) return "No exception"; } +/* the index should be in array bound. */ +#define KWSYSPE_IDX_CHK(RET) \ + if (!cp || idx >= cp->NumberOfCommands || idx < 0) { \ + return RET; \ + } + +int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(kwsysProcess_State_Error) + return cp->ProcessResults[idx].State; +} + +int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(kwsysProcess_Exception_Other) + return cp->ProcessResults[idx].ExitException; +} + +int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(-1) + return cp->ProcessResults[idx].ExitValue; +} + +int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(-1) + return cp->CommandExitCodes[idx]; +} + +const char* kwsysProcess_GetExceptionStringByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK("GetExceptionString called with NULL process management " + "structure or index out of bound") + if (cp->ProcessResults[idx].State == kwsysProcess_StateByIndex_Exception) { + return cp->ProcessResults[idx].ExitExceptionString; + } + return "No exception"; +} + +#undef KWSYSPE_IDX_CHK + void kwsysProcess_Execute(kwsysProcess* cp) { int i; @@ -1324,7 +1366,7 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) cp->ProcessResults[prPipe].ExitCode = cp->CommandExitCodes[prPipe]; if (WIFEXITED(cp->ProcessResults[prPipe].ExitCode)) { /* The child exited normally. */ - cp->ProcessResults[prPipe].State = kwsysProcess_State_Exited; + cp->ProcessResults[prPipe].State = kwsysProcess_StateByIndex_Exited; cp->ProcessResults[prPipe].ExitException = kwsysProcess_Exception_None; cp->ProcessResults[prPipe].ExitValue = (int)WEXITSTATUS(cp->ProcessResults[prPipe].ExitCode); @@ -1337,7 +1379,7 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) /* Error getting the child return code. */ strcpy(cp->ProcessResults[prPipe].ExitExceptionString, "Error getting child return code."); - cp->ProcessResults[prPipe].State = kwsysProcess_State_Error; + cp->ProcessResults[prPipe].State = kwsysProcess_StateByIndex_Error; } } /* support legacy state status value */ @@ -1503,7 +1545,7 @@ static int kwsysProcessInitialize(kwsysProcess* cp) sizeof(kwsysProcessResults) * (size_t)(cp->NumberOfCommands)); for (i = 0; i < cp->NumberOfCommands; i++) { cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None; - cp->ProcessResults[i].State = kwsysProcess_State_Starting; + cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Starting; cp->ProcessResults[i].ExitCode = 1; cp->ProcessResults[i].ExitValue = 1; strcpy(cp->ProcessResults[i].ExitExceptionString, "No exception"); diff --git a/ProcessWin32.c b/ProcessWin32.c index a9f68b3..5183e3d 100644 --- a/ProcessWin32.c +++ b/ProcessWin32.c @@ -892,6 +892,49 @@ const char* kwsysProcess_GetExceptionString(kwsysProcess* cp) return "No exception"; } +/* the index should be in array bound. */ +#define KWSYSPE_IDX_CHK(RET) \ + if (!cp || idx >= cp->NumberOfCommands || idx < 0) { \ + KWSYSPE_DEBUG((stderr, "array index out of bound\n")); \ + return RET; \ + } + +int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(kwsysProcess_State_Error) + return cp->ProcessResults[idx].State; +} + +int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(kwsysProcess_Exception_Other) + return cp->ProcessResults[idx].ExitException; +} + +int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(-1) + return cp->ProcessResults[idx].ExitValue; +} + +int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK(-1) + return cp->CommandExitCodes[idx]; +} + +const char* kwsysProcess_GetExceptionStringByIndex(kwsysProcess* cp, int idx) +{ + KWSYSPE_IDX_CHK("GetExceptionString called with NULL process management " + "structure or index out of bound") + if (cp->ProcessResults[idx].State == kwsysProcess_StateByIndex_Exception) { + return cp->ProcessResults[idx].ExitExceptionString; + } + return "No exception"; +} + +#undef KWSYSPE_IDX_CHK + void kwsysProcess_Execute(kwsysProcess* cp) { int i; @@ -1337,13 +1380,13 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) cp->ProcessResults[i].ExitCode = cp->CommandExitCodes[i]; if ((cp->ProcessResults[i].ExitCode & 0xF0000000) == 0xC0000000) { /* Child terminated due to exceptional behavior. */ - cp->ProcessResults[i].State = kwsysProcess_State_Exception; + cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Exception; cp->ProcessResults[i].ExitValue = 1; kwsysProcessSetExitExceptionByIndex(cp, cp->ProcessResults[i].ExitCode, i); } else { /* Child exited without exception. */ - cp->ProcessResults[i].State = kwsysProcess_State_Exited; + cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Exited; cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None; cp->ProcessResults[i].ExitValue = cp->ProcessResults[i].ExitCode; } @@ -1549,7 +1592,7 @@ int kwsysProcessInitialize(kwsysProcess* cp) sizeof(kwsysProcessResults) * cp->NumberOfCommands); for (i = 0; i < cp->NumberOfCommands; i++) { cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None; - cp->ProcessResults[i].State = kwsysProcess_State_Starting; + cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Starting; cp->ProcessResults[i].ExitCode = 1; cp->ProcessResults[i].ExitValue = 1; strcpy(cp->ProcessResults[i].ExitExceptionString, "No exception"); -- GitLab