aboutsummaryrefslogtreecommitdiff
path: root/src/backend/postmaster/postmaster.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/postmaster/postmaster.c')
-rw-r--r--src/backend/postmaster/postmaster.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 1bb3138a03a..000524dcb94 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -370,6 +370,7 @@ static DNSServiceRef bonjour_sdref = NULL;
/*
* postmaster.c - function prototypes
*/
+static void CloseServerPorts(int status, Datum arg);
static void unlink_external_pid_file(int status, Datum arg);
static void getInstallationPaths(const char *argv0);
static void checkDataDir(void);
@@ -900,6 +901,11 @@ PostmasterMain(int argc, char *argv[])
* interlock (thanks to whoever decided to put socket files in /tmp :-().
* For the same reason, it's best to grab the TCP socket(s) before the
* Unix socket(s).
+ *
+ * Also note that this internally sets up the on_proc_exit function that
+ * is responsible for removing both data directory and socket lockfiles;
+ * so it must happen before opening sockets so that at exit, the socket
+ * lockfiles go away after CloseServerPorts runs.
*/
CreateDataDirLockFile(true);
@@ -924,10 +930,15 @@ PostmasterMain(int argc, char *argv[])
/*
* Establish input sockets.
+ *
+ * First, mark them all closed, and set up an on_proc_exit function that's
+ * charged with closing the sockets again at postmaster shutdown.
*/
for (i = 0; i < MAXLISTEN; i++)
ListenSocket[i] = PGINVALID_SOCKET;
+ on_proc_exit(CloseServerPorts, 0);
+
if (ListenAddresses)
{
char *rawstring;
@@ -1272,6 +1283,42 @@ PostmasterMain(int argc, char *argv[])
/*
+ * on_proc_exit callback to close server's listen sockets
+ */
+static void
+CloseServerPorts(int status, Datum arg)
+{
+ int i;
+
+ /*
+ * First, explicitly close all the socket FDs. We used to just let this
+ * happen implicitly at postmaster exit, but it's better to close them
+ * before we remove the postmaster.pid lockfile; otherwise there's a race
+ * condition if a new postmaster wants to re-use the TCP port number.
+ */
+ for (i = 0; i < MAXLISTEN; i++)
+ {
+ if (ListenSocket[i] != PGINVALID_SOCKET)
+ {
+ StreamClose(ListenSocket[i]);
+ ListenSocket[i] = PGINVALID_SOCKET;
+ }
+ }
+
+ /*
+ * Next, remove any filesystem entries for Unix sockets. To avoid race
+ * conditions against incoming postmasters, this must happen after closing
+ * the sockets and before removing lock files.
+ */
+ RemoveSocketFiles();
+
+ /*
+ * We don't do anything about socket lock files here; those will be
+ * removed in a later on_proc_exit callback.
+ */
+}
+
+/*
* on_proc_exit callback to delete external_pid_file
*/
static void