ENH: Added test 7 to expose problems with polling by WaitForData.

This commit is contained in:
Brad King 2005-06-17 13:59:22 -04:00
parent 9fd4560ba2
commit 28ffc134a0

View File

@ -31,7 +31,7 @@
#endif #endif
int runChild(const char* cmd[], int state, int exception, int value, int runChild(const char* cmd[], int state, int exception, int value,
int share, int output, int delay, double timeout); int share, int output, int delay, double timeout, int poll);
int test1(int argc, const char* argv[]) int test1(int argc, const char* argv[])
{ {
@ -97,7 +97,7 @@ int test5(int argc, const char* argv[])
fflush(stdout); fflush(stdout);
fflush(stderr); fflush(stderr);
r = runChild(cmd, kwsysProcess_State_Exception, r = runChild(cmd, kwsysProcess_State_Exception,
kwsysProcess_Exception_Fault, 1, 1, 1, 0, 15); kwsysProcess_Exception_Fault, 1, 1, 1, 0, 15, 0);
fprintf(stdout, "Output on stdout after recursive test.\n"); fprintf(stdout, "Output on stdout after recursive test.\n");
fprintf(stderr, "Output on stderr after recursive test.\n"); fprintf(stderr, "Output on stderr after recursive test.\n");
fflush(stdout); fflush(stdout);
@ -125,13 +125,40 @@ void test6(int argc, const char* argv[])
} }
} }
/* Define MINPOLL to be one more than the number of times output is
written. Define MAXPOLL to be the largest number of times a loop
delaying 1/10th of a second should ever have to poll. */
#define MINPOLL 5
#define MAXPOLL 20
int test7(int argc, const char* argv[])
{
(void)argc; (void)argv;
fprintf(stdout, "Output on stdout before sleep.\n");
fprintf(stderr, "Output on stderr before sleep.\n");
fflush(stdout);
fflush(stderr);
/* Sleep for 1 second. */
#if defined(_WIN32)
Sleep(1000);
#else
usleep(1000000);
#endif
fprintf(stdout, "Output on stdout after sleep.\n");
fprintf(stderr, "Output on stderr after sleep.\n");
fflush(stdout);
fflush(stderr);
return 0;
}
int runChild(const char* cmd[], int state, int exception, int value, int runChild(const char* cmd[], int state, int exception, int value,
int share, int output, int delay, double timeout) int share, int output, int delay, double timeout,
int poll)
{ {
int result = 0; int result = 0;
char* data = 0; char* data = 0;
int length = 0; int length = 0;
double userTimeout = 0;
double* pUserTimeout = 0;
kwsysProcess* kp = kwsysProcess_New(); kwsysProcess* kp = kwsysProcess_New();
if(!kp) if(!kp)
{ {
@ -140,7 +167,10 @@ int runChild(const char* cmd[], int state, int exception, int value,
} }
kwsysProcess_SetCommand(kp, cmd); kwsysProcess_SetCommand(kp, cmd);
kwsysProcess_SetTimeout(kp, timeout); if(timeout >= 0)
{
kwsysProcess_SetTimeout(kp, timeout);
}
if(share) if(share)
{ {
kwsysProcess_SetPipeShared(kp, kwsysProcess_Pipe_STDOUT, 1); kwsysProcess_SetPipeShared(kp, kwsysProcess_Pipe_STDOUT, 1);
@ -148,14 +178,46 @@ int runChild(const char* cmd[], int state, int exception, int value,
} }
kwsysProcess_Execute(kp); kwsysProcess_Execute(kp);
if(poll)
{
pUserTimeout = &userTimeout;
}
if(!share) if(!share)
{ {
while(kwsysProcess_WaitForData(kp, &data, &length, 0)) int p;
while((p = kwsysProcess_WaitForData(kp, &data, &length, pUserTimeout)))
{ {
if(output) if(output)
{ {
fwrite(data, 1, length, stdout); if(poll && p == kwsysProcess_Pipe_Timeout)
fflush(stdout); {
fprintf(stdout, "WaitForData timeout reached.\n");
fflush(stdout);
/* Count the number of times we polled without getting data.
If it is excessive then kill the child and fail. */
if(++poll >= MAXPOLL)
{
fprintf(stdout, "Poll count reached limit %d.\n",
MAXPOLL);
kwsysProcess_Kill(kp);
}
}
else
{
fwrite(data, 1, length, stdout);
fflush(stdout);
}
}
if(poll)
{
/* Delay to avoid busy loop during polling. */
#if defined(_WIN32)
Sleep(100);
#else
usleep(100000);
#endif
} }
if(delay) if(delay)
{ {
@ -168,7 +230,7 @@ int runChild(const char* cmd[], int state, int exception, int value,
} }
kwsysProcess_WaitForExit(kp, 0); kwsysProcess_WaitForExit(kp, 0);
switch (kwsysProcess_GetState(kp)) switch (kwsysProcess_GetState(kp))
{ {
case kwsysProcess_State_Starting: case kwsysProcess_State_Starting:
@ -217,6 +279,15 @@ int runChild(const char* cmd[], int state, int exception, int value,
state, kwsysProcess_GetState(kp)); state, kwsysProcess_GetState(kp));
result = 1; result = 1;
} }
/* We should have polled more times than there were data if polling
was enabled. */
if(poll && poll < MINPOLL)
{
fprintf(stderr, "Poll count is %d, which is less than %d.\n",
poll, MINPOLL);
result = 1;
}
kwsysProcess_Delete(kp); kwsysProcess_Delete(kp);
return result; return result;
@ -250,7 +321,7 @@ int main(int argc, const char* argv[])
n = atoi(argv[2]); n = atoi(argv[2]);
} }
/* Check arguments. */ /* Check arguments. */
if(n < 1 || n > 6 || (argc == 3 && strcmp(argv[1], "run") != 0)) if(n < 1 || n > 7 || (argc == 3 && strcmp(argv[1], "run") != 0))
{ {
fprintf(stdout, "Usage: %s <test number>\n", argv[0]); fprintf(stdout, "Usage: %s <test number>\n", argv[0]);
return 1; return 1;
@ -265,35 +336,39 @@ int main(int argc, const char* argv[])
case 4: return test4(argc, argv); case 4: return test4(argc, argv);
case 5: return test5(argc, argv); case 5: return test5(argc, argv);
case 6: test6(argc, argv); return 0; case 6: test6(argc, argv); return 0;
case 7: return test7(argc, argv);
} }
fprintf(stderr, "Invalid test number %d.\n", n); fprintf(stderr, "Invalid test number %d.\n", n);
return 1; return 1;
} }
if(n >= 0 && n <= 6) if(n >= 0 && n <= 7)
{ {
int states[6] = int states[7] =
{ {
kwsysProcess_State_Exited, kwsysProcess_State_Exited,
kwsysProcess_State_Exited, kwsysProcess_State_Exited,
kwsysProcess_State_Expired, kwsysProcess_State_Expired,
kwsysProcess_State_Exception, kwsysProcess_State_Exception,
kwsysProcess_State_Exited, kwsysProcess_State_Exited,
kwsysProcess_State_Expired kwsysProcess_State_Expired,
kwsysProcess_State_Exited
}; };
int exceptions[6] = int exceptions[7] =
{ {
kwsysProcess_Exception_None, kwsysProcess_Exception_None,
kwsysProcess_Exception_None, kwsysProcess_Exception_None,
kwsysProcess_Exception_None, kwsysProcess_Exception_None,
kwsysProcess_Exception_Fault, kwsysProcess_Exception_Fault,
kwsysProcess_Exception_None, kwsysProcess_Exception_None,
kwsysProcess_Exception_None,
kwsysProcess_Exception_None kwsysProcess_Exception_None
}; };
int values[6] = {0, 123, 1, 1, 0, 0}; int values[7] = {0, 123, 1, 1, 0, 0, 0};
int outputs[6] = {1, 1, 1, 1, 1, 0}; int outputs[7] = {1, 1, 1, 1, 1, 0, 1};
int delays[6] = {0, 0, 0, 0, 0, 1}; int delays[7] = {0, 0, 0, 0, 0, 1, 0};
double timeouts[6] = {10, 10, 10, 10, 30, 10}; double timeouts[7] = {10, 10, 10, 10, 30, 10, -1};
int polls[7] = {0, 0, 0, 0, 0, 0, 1};
int r; int r;
const char* cmd[4]; const char* cmd[4];
#ifdef _WIN32 #ifdef _WIN32
@ -326,7 +401,8 @@ int main(int argc, const char* argv[])
fflush(stdout); fflush(stdout);
fflush(stderr); fflush(stderr);
r = runChild(cmd, states[n-1], exceptions[n-1], values[n-1], 0, r = runChild(cmd, states[n-1], exceptions[n-1], values[n-1], 0,
outputs[n-1], delays[n-1], timeouts[n-1]); outputs[n-1], delays[n-1], timeouts[n-1],
polls[n-1]);
fprintf(stdout, "Output on stdout after test %d.\n", n); fprintf(stdout, "Output on stdout after test %d.\n", n);
fprintf(stderr, "Output on stderr after test %d.\n", n); fprintf(stderr, "Output on stderr after test %d.\n", n);
fflush(stdout); fflush(stdout);