diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index 2fa64f1fb0a1ec9afc9e67fa326261d703497905..feaaf8f320200f6e6dde9004f7eb7af1bcaef998 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -11,7 +11,7 @@ * 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 $ * *------------------------------------------------------------------------- */ @@ -1305,14 +1305,15 @@ results_differ(const char *testname, const char *resultsfile, const char *defaul } /* - * 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; @@ -1327,9 +1328,10 @@ wait_for_tests(PID_TYPE * pids, char **names, int num_tests) while (tests_left > 0) { PID_TYPE p; + int exit_status; #ifndef WIN32 - p = wait(NULL); + p = wait(&exit_status); if (p == INVALID_PID) { @@ -1357,9 +1359,11 @@ wait_for_tests(PID_TYPE * pids, char **names, int num_tests) 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--; @@ -1373,6 +1377,35 @@ wait_for_tests(PID_TYPE * pids, char **names, int num_tests) #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 */ @@ -1385,6 +1418,7 @@ run_schedule(const char *schedule, test_function tfunc) _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; @@ -1486,7 +1520,7 @@ run_schedule(const char *schedule, test_function tfunc) { 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) @@ -1499,12 +1533,14 @@ run_schedule(const char *schedule, test_function tfunc) { 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 @@ -1514,7 +1550,7 @@ run_schedule(const char *schedule, test_function tfunc) { 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(); } @@ -1543,7 +1579,7 @@ run_schedule(const char *schedule, test_function tfunc) 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); @@ -1584,6 +1620,9 @@ run_schedule(const char *schedule, test_function tfunc) success_count++; } + if (statuses[i] != 0) + log_child_failure(statuses[i]); + status_end(); } } @@ -1598,6 +1637,7 @@ static void run_single_test(const char *test, test_function tfunc) { PID_TYPE pid; + int exit_status; _stringlist *resultfiles = NULL; _stringlist *expectfiles = NULL; _stringlist *tags = NULL; @@ -1608,7 +1648,7 @@ run_single_test(const char *test, test_function tfunc) 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. @@ -1624,7 +1664,7 @@ run_single_test(const char *test, test_function tfunc) 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); @@ -1645,6 +1685,10 @@ run_single_test(const char *test, test_function tfunc) status(_("ok")); success_count++; } + + if (exit_status != 0) + log_child_failure(exit_status); + status_end(); }