Skip to content

Commit 1dd56fd

Browse files
committed
Fix pg_plan_queries() to restore the previous setting of ActiveSnapshot
(probably NULL) before exiting. Up to now it's just left the variable as it set it, which means that after we're done processing the current client message, ActiveSnapshot is probably pointing at garbage (because this function is typically run in MessageContext which will get reset). There doesn't seem to have been any code path in which that mattered before 8.3, but now the plancache module might try to use the stale value if the next client message is a Bind for a prepared statement that is in need of replanning. Per report from Alex Hunsaker.
1 parent d2ab94d commit 1dd56fd

File tree

1 file changed

+35
-17
lines changed

1 file changed

+35
-17
lines changed

src/backend/tcop/postgres.c

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.542 2008/01/26 19:55:08 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.542.2.1 2008/03/12 23:58:35 tgl Exp $
1212
*
1313
* NOTES
1414
* this is the "main" module of the postgres backend and
@@ -729,31 +729,49 @@ List *
729729
pg_plan_queries(List *querytrees, int cursorOptions, ParamListInfo boundParams,
730730
bool needSnapshot)
731731
{
732-
List *stmt_list = NIL;
733-
ListCell *query_list;
732+
List * volatile stmt_list = NIL;
733+
Snapshot saveActiveSnapshot = ActiveSnapshot;
734734

735-
foreach(query_list, querytrees)
735+
/* PG_TRY to ensure previous ActiveSnapshot is restored on error */
736+
PG_TRY();
736737
{
737-
Query *query = (Query *) lfirst(query_list);
738-
Node *stmt;
738+
Snapshot mySnapshot = NULL;
739+
ListCell *query_list;
739740

740-
if (query->commandType == CMD_UTILITY)
741+
foreach(query_list, querytrees)
741742
{
742-
/* Utility commands have no plans. */
743-
stmt = query->utilityStmt;
744-
}
745-
else
746-
{
747-
if (needSnapshot)
743+
Query *query = (Query *) lfirst(query_list);
744+
Node *stmt;
745+
746+
if (query->commandType == CMD_UTILITY)
747+
{
748+
/* Utility commands have no plans. */
749+
stmt = query->utilityStmt;
750+
}
751+
else
748752
{
749-
ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
750-
needSnapshot = false;
753+
if (needSnapshot && mySnapshot == NULL)
754+
{
755+
mySnapshot = CopySnapshot(GetTransactionSnapshot());
756+
ActiveSnapshot = mySnapshot;
757+
}
758+
stmt = (Node *) pg_plan_query(query, cursorOptions,
759+
boundParams);
751760
}
752-
stmt = (Node *) pg_plan_query(query, cursorOptions, boundParams);
761+
762+
stmt_list = lappend(stmt_list, stmt);
753763
}
754764

755-
stmt_list = lappend(stmt_list, stmt);
765+
if (mySnapshot)
766+
FreeSnapshot(mySnapshot);
767+
}
768+
PG_CATCH();
769+
{
770+
ActiveSnapshot = saveActiveSnapshot;
771+
PG_RE_THROW();
756772
}
773+
PG_END_TRY();
774+
ActiveSnapshot = saveActiveSnapshot;
757775

758776
return stmt_list;
759777
}

0 commit comments

Comments
 (0)