summaryrefslogtreecommitdiff
path: root/src/backend/postmaster/postmaster.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2015-10-06 17:15:27 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2015-10-06 17:15:27 -0400
commit3d10f39709941f5562adf3d0fc4d61f91fac5ff5 (patch)
tree04b96ca0818457d9d56fac322dcd40eacb746df2 /src/backend/postmaster/postmaster.c
parent69157086413efb8c1de793aa4493187c819cc5ae (diff)
Perform an immediate shutdown if the postmaster.pid file is removed.
The postmaster now checks every minute or so (worst case, at most two minutes) that postmaster.pid is still there and still contains its own PID. If not, it performs an immediate shutdown, as though it had received SIGQUIT. The original goal behind this change was to ensure that failed buildfarm runs would get fully cleaned up, even if the test scripts had left a postmaster running, which is not an infrequent occurrence. When the buildfarm script removes a test postmaster's $PGDATA directory, its next check on postmaster.pid will fail and cause it to exit. Previously, manual intervention was often needed to get rid of such orphaned postmasters, since they'd block new test postmasters from obtaining the expected socket address. However, by checking postmaster.pid and not something else, we can provide additional robustness: manual removal of postmaster.pid is a frequent DBA mistake, and now we can at least limit the damage that will ensue if a new postmaster is started while the old one is still alive. Back-patch to all supported branches, since we won't get the desired improvement in buildfarm reliability otherwise.
Diffstat (limited to 'src/backend/postmaster/postmaster.c')
-rw-r--r--src/backend/postmaster/postmaster.c54
1 files changed, 42 insertions, 12 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index dd87e430434..40e655f6855 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -1372,9 +1372,10 @@ ServerLoop(void)
fd_set readmask;
int nSockets;
time_t now,
+ last_lockfile_recheck_time,
last_touch_time;
- last_touch_time = time(NULL);
+ last_lockfile_recheck_time = last_touch_time = time(NULL);
nSockets = initMasks(&readmask);
@@ -1520,27 +1521,56 @@ ServerLoop(void)
kill(AutoVacPID, SIGUSR2);
}
+#ifdef HAVE_PTHREAD_IS_THREADED_NP
+
+ /*
+ * With assertions enabled, check regularly for appearance of
+ * additional threads. All builds check at start and exit.
+ */
+ Assert(pthread_is_threaded_np() == 0);
+#endif
+
+ /*
+ * Lastly, check to see if it's time to do some things that we don't
+ * want to do every single time through the loop, because they're a
+ * bit expensive. Note that there's up to a minute of slop in when
+ * these tasks will be performed, since DetermineSleepTime() will let
+ * us sleep at most that long.
+ */
+ now = time(NULL);
+
/*
- * Touch the socket and lock file every 58 minutes, to ensure that
+ * Once a minute, verify that postmaster.pid hasn't been removed or
+ * overwritten. If it has, we force a shutdown. This avoids having
+ * postmasters and child processes hanging around after their database
+ * is gone, and maybe causing problems if a new database cluster is
+ * created in the same place. It also provides some protection
+ * against a DBA foolishly removing postmaster.pid and manually
+ * starting a new postmaster. Data corruption is likely to ensue from
+ * that anyway, but we can minimize the damage by aborting ASAP.
+ */
+ if (now - last_lockfile_recheck_time >= 1 * SECS_PER_MINUTE)
+ {
+ if (!RecheckDataDirLockFile())
+ {
+ ereport(LOG,
+ (errmsg("performing immediate shutdown because data directory lock file is invalid")));
+ kill(MyProcPid, SIGQUIT);
+ }
+ last_lockfile_recheck_time = now;
+ }
+
+ /*
+ * Touch Unix socket and lock file every 58 minutes, to ensure that
* they are not removed by overzealous /tmp-cleaning tasks. We assume
* no one runs cleaners with cutoff times of less than an hour ...
*/
- now = time(NULL);
if (now - last_touch_time >= 58 * SECS_PER_MINUTE)
{
TouchSocketFile();
TouchSocketLockFile();
last_touch_time = now;
}
-
-#ifdef HAVE_PTHREAD_IS_THREADED_NP
-
- /*
- * With assertions enabled, check regularly for appearance of
- * additional threads. All builds check at start and exit.
- */
- Assert(pthread_is_threaded_np() == 0);
-#endif
}
}