diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
index 1c4847abea1b3b0bf9488db00df722a457b50c8c..05aac8fde9cd5a05c8e351f25b9ab79e0e31eb42 100644
--- a/contrib/pg_upgrade/check.c
+++ b/contrib/pg_upgrade/check.c
@@ -131,7 +131,7 @@ report_clusters_compatible(void)
 		pg_log(PG_REPORT, "\n*Clusters are compatible*\n");
 		/* stops new cluster */
 		stop_postmaster(false, false);
-		exit_nicely(false);
+		exit(0);
 	}
 
 	pg_log(PG_REPORT, "\n"
diff --git a/contrib/pg_upgrade/option.c b/contrib/pg_upgrade/option.c
index c984535461bee10d091c22d48d64db8d4a226e9d..857d6528c8a1fd867f2d8c3c64aede0074518eac 100644
--- a/contrib/pg_upgrade/option.c
+++ b/contrib/pg_upgrade/option.c
@@ -77,12 +77,12 @@ parseCommandLine(int argc, char *argv[])
 			strcmp(argv[1], "-?") == 0)
 		{
 			usage();
-			exit_nicely(false);
+			exit(0);
 		}
 		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
 		{
 			pg_log(PG_REPORT, "pg_upgrade " PG_VERSION "\n");
-			exit_nicely(false);
+			exit(0);
 		}
 	}
 
@@ -125,7 +125,7 @@ parseCommandLine(int argc, char *argv[])
 				if ((log_opts.debug_fd = fopen(optarg, "w")) == NULL)
 				{
 					pg_log(PG_FATAL, "cannot open debug file\n");
-					exit_nicely(false);
+					exit(1);
 				}
 				break;
 
@@ -141,7 +141,7 @@ parseCommandLine(int argc, char *argv[])
 				if ((old_cluster.port = atoi(optarg)) <= 0)
 				{
 					pg_log(PG_FATAL, "invalid old port number\n");
-					exit_nicely(false);
+					exit(1);
 				}
 				break;
 
@@ -149,7 +149,7 @@ parseCommandLine(int argc, char *argv[])
 				if ((new_cluster.port = atoi(optarg)) <= 0)
 				{
 					pg_log(PG_FATAL, "invalid new port number\n");
-					exit_nicely(false);
+					exit(1);
 				}
 				break;
 
diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h
index 446195273c1cf307e331c3822a421af8c3e62447..8f72ea80d7ad9eb448a602de1f33b70a362b23f4 100644
--- a/contrib/pg_upgrade/pg_upgrade.h
+++ b/contrib/pg_upgrade/pg_upgrade.h
@@ -363,7 +363,6 @@ void		check_for_libpq_envvars(void);
 
 /* util.c */
 
-void		exit_nicely(bool need_cleanup);
 char	   *quote_identifier(const char *s);
 int			get_user_info(char **user_name);
 void		check_ok(void);
diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c
index 022f69742e5c1db2e9dd652d274a2134c0121164..b0df99cede6120cfe0ca82a35e4ad79cee6e333d 100644
--- a/contrib/pg_upgrade/server.c
+++ b/contrib/pg_upgrade/server.c
@@ -23,7 +23,7 @@ static bool test_server_conn(ClusterInfo *cluster, int timeout);
  *
  *	Connects to the desired database on the designated server.
  *	If the connection attempt fails, this function logs an error
- *	message and calls exit_nicely() to kill the program.
+ *	message and calls exit() to kill the program.
  */
 PGconn *
 connectToServer(ClusterInfo *cluster, const char *db_name)
@@ -45,7 +45,8 @@ connectToServer(ClusterInfo *cluster, const char *db_name)
 		if (conn)
 			PQfinish(conn);
 
-		exit_nicely(true);
+		printf("Failure, exiting\n");
+		exit(1);
 	}
 
 	return conn;
@@ -57,7 +58,7 @@ connectToServer(ClusterInfo *cluster, const char *db_name)
  *
  *	Formats a query string from the given arguments and executes the
  *	resulting query.  If the query fails, this function logs an error
- *	message and calls exit_nicely() to kill the program.
+ *	message and calls exit() to kill the program.
  */
 PGresult *
 executeQueryOrDie(PGconn *conn, const char *fmt,...)
@@ -81,8 +82,8 @@ executeQueryOrDie(PGconn *conn, const char *fmt,...)
 			   PQerrorMessage(conn));
 		PQclear(result);
 		PQfinish(conn);
-		exit_nicely(true);
-		return NULL;			/* Never get here, but keeps compiler happy */
+		printf("Failure, exiting\n");
+		exit(1);
 	}
 	else
 		return result;
@@ -152,6 +153,18 @@ get_major_server_version(ClusterInfo *cluster)
 }
 
 
+static void
+#ifdef HAVE_ATEXIT
+stop_postmaster_atexit(void)
+#else
+stop_postmaster_on_exit(int exitstatus, void *arg)
+#endif
+{
+	stop_postmaster(true, true);
+
+}
+
+
 void
 start_postmaster(ClusterInfo *cluster, bool quiet)
 {
@@ -159,11 +172,22 @@ start_postmaster(ClusterInfo *cluster, bool quiet)
 	const char *bindir;
 	const char *datadir;
 	unsigned short port;
+	bool		exit_hook_registered = false;
 
 	bindir = cluster->bindir;
 	datadir = cluster->pgdata;
 	port = cluster->port;
 
+	if (!exit_hook_registered)
+	{
+#ifdef HAVE_ATEXIT
+		atexit(stop_postmaster_atexit);
+#else
+		on_exit(stop_postmaster_on_exit);
+#endif
+		exit_hook_registered = true;
+	}
+
 	/*
 	 * On Win32, we can't send both pg_upgrade output and pg_ctl output to the
 	 * same file because we get the error: "The process cannot access the file
diff --git a/contrib/pg_upgrade/util.c b/contrib/pg_upgrade/util.c
index f957508101382a6065b0b7b9458ee4c52316e920..804aa0d1e5fa2900cdb59cffea565315294fe503 100644
--- a/contrib/pg_upgrade/util.c
+++ b/contrib/pg_upgrade/util.c
@@ -99,7 +99,8 @@ pg_log(eLogType type, char *fmt,...)
 		case PG_FATAL:
 			printf("%s", "\n");
 			printf("%s", _(message));
-			exit_nicely(true);
+			printf("Failure, exiting\n");
+			exit(1);
 			break;
 
 		case PG_DEBUG:
@@ -184,36 +185,6 @@ get_user_info(char **user_name)
 }
 
 
-void
-exit_nicely(bool need_cleanup)
-{
-	stop_postmaster(true, true);
-
-	pg_free(log_opts.filename);
-
-	if (log_opts.fd)
-		fclose(log_opts.fd);
-
-	if (log_opts.debug_fd)
-		fclose(log_opts.debug_fd);
-
-	/* terminate any running instance of postmaster */
-	if (os_info.postmasterPID != 0)
-		kill(os_info.postmasterPID, SIGTERM);
-	
-	if (need_cleanup)
-	{
-		printf("Failure, exiting\n");
-		/*
-		 * FIXME must delete intermediate files
-		 */
-		exit(1);
-	}
-	else
-		exit(0);
-}
-
-
 void *
 pg_malloc(int n)
 {