Skip to content

Commit dd9c6ff

Browse files
committed
Fix longstanding race condition in plancache.c.
When creating or manipulating a cached plan for a transaction control command (particularly ROLLBACK), we must not perform any catalog accesses, since we might be in an aborted transaction. However, plancache.c busily saved or examined the search_path for every cached plan. If we were unlucky enough to do this at a moment where the path's expansion into schema OIDs wasn't already cached, we'd do some catalog accesses; and with some more bad luck such as an ill-timed signal arrival, that could lead to crashes or Assert failures, as exhibited in bug #8095 from Nachiket Vaidya. Fortunately, there's no real need to consider the search path for such commands, so we can just skip the relevant steps when the subject statement is a TransactionStmt. This is somewhat related to bug #5269, though the failure happens during initial cached-plan creation rather than revalidation. This bug has been there since the plan cache was invented, so back-patch to all supported branches.
1 parent 8e00c48 commit dd9c6ff

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

src/backend/utils/cache/plancache.c

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@
6161
#include "utils/syscache.h"
6262

6363

64+
/*
65+
* We must skip "overhead" operations that involve database access when the
66+
* cached plan's subject statement is a transaction control command.
67+
*/
68+
#define IsTransactionStmtPlan(plansource) \
69+
((plansource)->raw_parse_tree && \
70+
IsA((plansource)->raw_parse_tree, TransactionStmt))
71+
6472
static List *cached_plans_list = NIL;
6573

6674
static void StoreCachedPlan(CachedPlanSource *plansource, List *stmt_list,
@@ -136,9 +144,13 @@ CreateCachedPlan(Node *raw_parse_tree,
136144

137145
/*
138146
* Fetch current search_path into new context, but do any recalculation
139-
* work required in caller's context.
147+
* work required in caller's context. Skip this for a transaction control
148+
* command, since we won't need it and can't risk catalog access.
140149
*/
141-
search_path = GetOverrideSearchPath(source_context);
150+
if (raw_parse_tree && IsA(raw_parse_tree, TransactionStmt))
151+
search_path = NULL;
152+
else
153+
search_path = GetOverrideSearchPath(source_context);
142154

143155
/*
144156
* Create and fill the CachedPlanSource struct within the new context.
@@ -229,9 +241,13 @@ FastCreateCachedPlan(Node *raw_parse_tree,
229241

230242
/*
231243
* Fetch current search_path into given context, but do any recalculation
232-
* work required in caller's context.
244+
* work required in caller's context. Skip this for a transaction control
245+
* command, since we won't need it and can't risk catalog access.
233246
*/
234-
search_path = GetOverrideSearchPath(context);
247+
if (raw_parse_tree && IsA(raw_parse_tree, TransactionStmt))
248+
search_path = NULL;
249+
else
250+
search_path = GetOverrideSearchPath(context);
235251

236252
/*
237253
* Create and fill the CachedPlanSource struct within the given context.
@@ -517,7 +533,8 @@ RevalidateCachedPlan(CachedPlanSource *plansource, bool useResOwner)
517533
*
518534
* (XXX is there anything else we really need to restore?)
519535
*/
520-
PushOverrideSearchPath(plansource->search_path);
536+
if (plansource->search_path)
537+
PushOverrideSearchPath(plansource->search_path);
521538

522539
/*
523540
* If a snapshot is already set (the normal case), we can just use
@@ -601,7 +618,8 @@ RevalidateCachedPlan(CachedPlanSource *plansource, bool useResOwner)
601618
PopActiveSnapshot();
602619

603620
/* Now we can restore current search path */
604-
PopOverrideSearchPath();
621+
if (plansource->search_path)
622+
PopOverrideSearchPath();
605623

606624
/*
607625
* Store the plans into the plancache entry, advancing the generation

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy