Don't call the function that may raise an error while holding spinlock.
authorFujii Masao <fujii@postgresql.org>
Thu, 20 Apr 2017 14:12:57 +0000 (23:12 +0900)
committerFujii Masao <fujii@postgresql.org>
Thu, 20 Apr 2017 14:12:57 +0000 (23:12 +0900)
It's not safe to raise an error while holding spinlock. But previously
logical replication worker for table sync called the function which
reads the system catalog and may raise an error while it's holding
spinlock. Which could lead to the trouble where spinlock will never
be released and the server gets stuck infinitely.

Author: Petr Jelinek
Reviewed-by: Kyotaro Horiguchi and Fujii Masao
Reported-by: Fujii Masao
Discussion: http://postgr.es/m/CAHGQGwFDWh_Qr-q_GEMpD+qH=vYPMdVqw=ZOSY3kX_Pna9R9SA@mail.gmail.com

src/backend/replication/logical/tablesync.c

index 108326bef1c4100b3c8e1a3f70436b01e881c0e3..b4b48d92cf43d340740b0a872a5c50a444b87f49 100644 (file)
@@ -705,17 +705,20 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
 {
    char           *slotname;
    char           *err;
+   char        relstate;
+   XLogRecPtr  relstate_lsn;
 
    /* Check the state of the table synchronization. */
    StartTransactionCommand();
+   relstate = GetSubscriptionRelState(MyLogicalRepWorker->subid,
+                                      MyLogicalRepWorker->relid,
+                                      &relstate_lsn, false);
+   CommitTransactionCommand();
+
    SpinLockAcquire(&MyLogicalRepWorker->relmutex);
-   MyLogicalRepWorker->relstate =
-       GetSubscriptionRelState(MyLogicalRepWorker->subid,
-                               MyLogicalRepWorker->relid,
-                               &MyLogicalRepWorker->relstate_lsn,
-                               false);
+   MyLogicalRepWorker->relstate = relstate;
+   MyLogicalRepWorker->relstate_lsn = relstate_lsn;
    SpinLockRelease(&MyLogicalRepWorker->relmutex);
-   CommitTransactionCommand();
 
    /*
     * To build a slot name for the sync work, we are limited to NAMEDATALEN -