]> granicus.if.org Git - postgresql/commitdiff
Fix some more bugs in signal handlers and process shutdown logic.
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 1 Feb 2014 21:21:00 +0000 (16:21 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 1 Feb 2014 21:21:30 +0000 (16:21 -0500)
WalSndKill was doing things exactly backwards: it should first clear
MyWalSnd (to stop signal handlers from touching MyWalSnd->latch),
then disown the latch, and only then mark the WalSnd struct unused by
clearing its pid field.

Also, WalRcvSigUsr1Handler and worker_spi_sighup failed to preserve
errno, which is surely a requirement for any signal handler.

Per discussion of recent buildfarm failures.  Back-patch as far
as the relevant code exists.

contrib/worker_spi/worker_spi.c
src/backend/replication/walreceiver.c
src/backend/replication/walsender.c

index 99501fa56680e14699c01868945beca95abc155d..beffab1cad25b6e45478f4e8f4c1b9cf3d05efb5 100644 (file)
@@ -79,15 +79,19 @@ worker_spi_sigterm(SIGNAL_ARGS)
 
 /*
  * Signal handler for SIGHUP
- *             Set a flag to let the main loop to reread the config file, and set
+ *             Set a flag to tell the main loop to reread the config file, and set
  *             our latch to wake it up.
  */
 static void
 worker_spi_sighup(SIGNAL_ARGS)
 {
+       int                     save_errno = errno;
+
        got_sighup = true;
        if (MyProc)
                SetLatch(&MyProc->procLatch);
+
+       errno = save_errno;
 }
 
 /*
index 7fe80a94a3075d66a8b7334468391209a6210d20..ae087535f780c50d26e8e883a07fbf0a983b888a 100644 (file)
@@ -737,7 +737,11 @@ WalRcvSigHupHandler(SIGNAL_ARGS)
 static void
 WalRcvSigUsr1Handler(SIGNAL_ARGS)
 {
+       int                     save_errno = errno;
+
        latch_sigusr1_handler();
+
+       errno = save_errno;
 }
 
 /* SIGTERM: set flag for main loop, or shutdown immediately if safe */
index afd559dae46a567f4685bc6c103d07be93e1d809..cdd9c6a5334a13b952235487bedd6e738fedd9b3 100644 (file)
@@ -1214,17 +1214,23 @@ InitWalSenderSlot(void)
 static void
 WalSndKill(int code, Datum arg)
 {
-       Assert(MyWalSnd != NULL);
+       WalSnd     *walsnd = MyWalSnd;
+
+       Assert(walsnd != NULL);
+
+       /*
+        * Clear MyWalSnd first; then disown the latch.  This is so that signal
+        * handlers won't try to touch the latch after it's no longer ours.
+        */
+       MyWalSnd = NULL;
+
+       DisownLatch(&walsnd->latch);
 
        /*
         * Mark WalSnd struct no longer in use. Assume that no lock is required
         * for this.
         */
-       MyWalSnd->pid = 0;
-       DisownLatch(&MyWalSnd->latch);
-
-       /* WalSnd struct isn't mine anymore */
-       MyWalSnd = NULL;
+       walsnd->pid = 0;
 }
 
 /*