Fix NULL pointer access in logical replication workers
authorPeter Eisentraut <peter_e@gmx.net>
Mon, 23 Jan 2017 17:33:27 +0000 (12:33 -0500)
committerPeter Eisentraut <peter_e@gmx.net>
Mon, 23 Jan 2017 17:33:27 +0000 (12:33 -0500)
From: Petr Jelinek <pjmodos@pjmodos.net>

src/backend/replication/logical/launcher.c
src/backend/replication/logical/worker.c

index b5240dcedeba6ddd302543f9ec96a86d54ac913f..18919724af4a0c018e88d1405c6b4fc074a0a496 100644 (file)
@@ -349,10 +349,21 @@ logicalrep_worker_stop(Oid subid)
 
                ResetLatch(&MyProc->procLatch);
 
-               /* Check if the worker has started. */
+               /* Check worker status. */
                LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
-               worker = logicalrep_worker_find(subid);
-               if (!worker || worker->proc)
+
+               /*
+                * Worker is no longer associated with subscription.  It must have
+                * exited, nothing more for us to do.
+                */
+               if (worker->subid == InvalidOid)
+               {
+                       LWLockRelease(LogicalRepWorkerLock);
+                       return;
+               }
+
+               /* Worker has assigned proc, so it has started. */
+               if (worker->proc)
                        break;
        }
 
index 7d86736444b9125e243e206d238147d26d5843f3..3ee9cc12df04db69c2780198419258fa242ec97e 100644 (file)
@@ -1219,14 +1219,15 @@ reread_subscription(void)
        newsub = GetSubscription(MyLogicalRepWorker->subid, true);
 
        /*
-        * Exit if connection string was changed. The launcher will start
-        * new worker.
+        * Exit if the subscription was removed.
+        * This normally should not happen as the worker gets killed
+        * during DROP SUBSCRIPTION.
         */
-       if (strcmp(newsub->conninfo, MySubscription->conninfo) != 0)
+       if (!newsub)
        {
                ereport(LOG,
                                (errmsg("logical replication worker for subscription \"%s\" will "
-                                               "restart because the connection information was changed",
+                                               "stop because the subscription was removed",
                                                MySubscription->name)));
 
                walrcv_disconnect(wrconn);
@@ -1234,14 +1235,14 @@ reread_subscription(void)
        }
 
        /*
-        * Exit if publication list was changed. The launcher will start
+        * Exit if connection string was changed. The launcher will start
         * new worker.
         */
-       if (!equal(newsub->publications, MySubscription->publications))
+       if (strcmp(newsub->conninfo, MySubscription->conninfo) != 0)
        {
                ereport(LOG,
                                (errmsg("logical replication worker for subscription \"%s\" will "
-                                               "restart because subscription's publications were changed",
+                                               "restart because the connection information was changed",
                                                MySubscription->name)));
 
                walrcv_disconnect(wrconn);
@@ -1249,15 +1250,14 @@ reread_subscription(void)
        }
 
        /*
-        * Exit if the subscription was removed.
-        * This normally should not happen as the worker gets killed
-        * during DROP SUBSCRIPTION.
+        * Exit if publication list was changed. The launcher will start
+        * new worker.
         */
-       if (!newsub)
+       if (!equal(newsub->publications, MySubscription->publications))
        {
                ereport(LOG,
                                (errmsg("logical replication worker for subscription \"%s\" will "
-                                               "stop because the subscription was removed",
+                                               "restart because subscription's publications were changed",
                                                MySubscription->name)));
 
                walrcv_disconnect(wrconn);