aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/commands/trigger.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 98b82074b5f..91ef779c65a 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -2662,6 +2662,16 @@ ltrmark:;
buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
+ /*
+ * Although we already know this tuple is valid, we must lock the
+ * buffer to ensure that no one has a buffer cleanup lock; otherwise
+ * they might move the tuple while we try to copy it. But we can
+ * release the lock before actually doing the heap_copytuple call,
+ * since holding pin is sufficient to prevent anyone from getting a
+ * cleanup lock they don't already hold.
+ */
+ LockBuffer(buffer, BUFFER_LOCK_SHARE);
+
page = BufferGetPage(buffer);
lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
@@ -2671,6 +2681,8 @@ ltrmark:;
tuple.t_len = ItemIdGetLength(lp);
tuple.t_self = *tid;
tuple.t_tableOid = RelationGetRelid(relation);
+
+ LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
}
result = heap_copytuple(&tuple);