* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/test/regress/pg_regress.c,v 1.44 2008/03/31 01:31:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/test/regress/pg_regress.c,v 1.45 2008/05/17 20:02:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
}
/*
- * Wait for specified subprocesses to finish
+ * Wait for specified subprocesses to finish, and return their exit
+ * statuses into statuses[]
*
- * If names isn't NULL, report each subprocess as it finishes
+ * If names isn't NULL, print each subprocess's name as it finishes
*
* Note: it's OK to scribble on the pids array, but not on the names array
*/
static void
-wait_for_tests(PID_TYPE * pids, char **names, int num_tests)
+wait_for_tests(PID_TYPE *pids, int *statuses, char **names, int num_tests)
{
int tests_left;
int i;
while (tests_left > 0)
{
PID_TYPE p;
+ int exit_status;
#ifndef WIN32
- p = wait(NULL);
+ p = wait(&exit_status);
if (p == INVALID_PID)
{
if (p == pids[i])
{
#ifdef WIN32
+ GetExitCodeProcess(pids[i], &exit_status);
CloseHandle(pids[i]);
#endif
pids[i] = INVALID_PID;
+ statuses[i] = exit_status;
if (names)
status(" %s", names[i]);
tests_left--;
#endif
}
+/*
+ * report nonzero exit code from a test process
+ */
+static void
+log_child_failure(int exitstatus)
+{
+ if (WIFEXITED(exitstatus))
+ status(_(" (test process exited with exit code %d)"),
+ WEXITSTATUS(exitstatus));
+ else if (WIFSIGNALED(exitstatus))
+ {
+#if defined(WIN32)
+ status(_(" (test process was terminated by exception 0x%X)"),
+ WTERMSIG(exitstatus));
+#elif defined(HAVE_DECL_SYS_SIGLIST) && HAVE_DECL_SYS_SIGLIST
+ status(_(" (test process was terminated by signal %d: %s)"),
+ WTERMSIG(exitstatus),
+ WTERMSIG(exitstatus) < NSIG ?
+ sys_siglist[WTERMSIG(exitstatus)] : "(unknown))");
+#else
+ status(_(" (test process was terminated by signal %d)"),
+ WTERMSIG(exitstatus));
+#endif
+ }
+ else
+ status(_(" (test process exited with unrecognized status %d)"),
+ exitstatus);
+}
+
/*
* Run all the tests specified in one schedule file
*/
_stringlist *expectfiles[MAX_PARALLEL_TESTS];
_stringlist *tags[MAX_PARALLEL_TESTS];
PID_TYPE pids[MAX_PARALLEL_TESTS];
+ int statuses[MAX_PARALLEL_TESTS];
_stringlist *ignorelist = NULL;
char scbuf[1024];
FILE *scf;
{
status(_("test %-20s ... "), tests[0]);
pids[0] = (tfunc) (tests[0], &resultfiles[0], &expectfiles[0], &tags[0]);
- wait_for_tests(pids, NULL, 1);
+ wait_for_tests(pids, statuses, NULL, 1);
/* status line is finished below */
}
else if (max_connections > 0 && max_connections < num_tests)
{
if (i - oldest >= max_connections)
{
- wait_for_tests(pids + oldest, tests + oldest, i - oldest);
+ wait_for_tests(pids + oldest, statuses + oldest,
+ tests + oldest, i - oldest);
oldest = i;
}
pids[i] = (tfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
}
- wait_for_tests(pids + oldest, tests + oldest, i - oldest);
+ wait_for_tests(pids + oldest, statuses + oldest,
+ tests + oldest, i - oldest);
status_end();
}
else
{
pids[i] = (tfunc) (tests[i], &resultfiles[i], &expectfiles[i], &tags[i]);
}
- wait_for_tests(pids, tests, num_tests);
+ wait_for_tests(pids, statuses, tests, num_tests);
status_end();
}
bool newdiff;
if (tl)
- tl = tl->next; /* tl has the same lengt has rl and el
+ tl = tl->next; /* tl has the same length as rl and el
* if it exists */
newdiff = results_differ(tests[i], rl->str, el->str);
success_count++;
}
+ if (statuses[i] != 0)
+ log_child_failure(statuses[i]);
+
status_end();
}
}
run_single_test(const char *test, test_function tfunc)
{
PID_TYPE pid;
+ int exit_status;
_stringlist *resultfiles = NULL;
_stringlist *expectfiles = NULL;
_stringlist *tags = NULL;
status(_("test %-20s ... "), test);
pid = (tfunc) (test, &resultfiles, &expectfiles, &tags);
- wait_for_tests(&pid, NULL, 1);
+ wait_for_tests(&pid, &exit_status, NULL, 1);
/*
* Advance over all three lists simultaneously.
bool newdiff;
if (tl)
- tl = tl->next; /* tl has the same lengt has rl and el if it
+ tl = tl->next; /* tl has the same length as rl and el if it
* exists */
newdiff = results_differ(test, rl->str, el->str);
status(_("ok"));
success_count++;
}
+
+ if (exit_status != 0)
+ log_child_failure(exit_status);
+
status_end();
}