diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 98b82074b5f49672f25175de3ba422d605e67bb4..91ef779c65a88fcd53e389c2d798fc492da9ccbd 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);