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();
 }