aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2016-10-23 19:14:32 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2016-10-23 19:14:32 -0400
commitbeac79369411f62615d465953b9e6da1296758dc (patch)
tree32ed0de9d98222bbaa4e83641a9a40ad5ebf196c
parent65d85b8f9dc3768b3b5bf59187620e9c7cafcb47 (diff)
downloadpostgresql-beac79369411f62615d465953b9e6da1296758dc.tar.gz
postgresql-beac79369411f62615d465953b9e6da1296758dc.zip
Avoid testing tuple visibility without buffer lock.
INSERT ... ON CONFLICT (specifically ExecCheckHeapTupleVisible) contains another example of this unsafe coding practice. It is much harder to get a failure out of it than the case fixed in commit 6292c2339, because in most scenarios any hint bits that could be set would have already been set earlier in the command. However, Konstantin Knizhnik reported a failure with a custom transaction manager, and it's clearly possible to get a failure via a race condition in async-commit mode. For lack of a reproducible example, no regression test case in this commit. I did some testing with Asserts added to tqual.c's functions, and can say that running "make check-world" exposed these two bugs and no others. The Asserts are messy enough that I've not added them to the code for now. Report: <57EE93C8.8080504@postgrespro.ru> Related-Discussion: <CAO3NbwOycQjt2Oqy2VW-eLTq2M5uGMyHnGm=RNga4mjqcYD7gQ@mail.gmail.com>
-rw-r--r--src/backend/executor/nodeModifyTable.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 9d10467303c..05b6e3337f8 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -177,6 +177,11 @@ ExecCheckHeapTupleVisible(EState *estate,
if (!IsolationUsesXactSnapshot())
return;
+ /*
+ * We need buffer pin and lock to call HeapTupleSatisfiesVisibility.
+ * Caller should be holding pin, but not lock.
+ */
+ LockBuffer(buffer, BUFFER_LOCK_SHARE);
if (!HeapTupleSatisfiesVisibility(tuple, estate->es_snapshot, buffer))
{
/*
@@ -190,6 +195,7 @@ ExecCheckHeapTupleVisible(EState *estate,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not serialize access due to concurrent update")));
}
+ LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
}
/*