diff --git a/src/backend/storage/lmgr/deadlock.c b/src/backend/storage/lmgr/deadlock.c index 288186a6ce..697ef6e495 100644 --- a/src/backend/storage/lmgr/deadlock.c +++ b/src/backend/storage/lmgr/deadlock.c @@ -527,25 +527,6 @@ FindLockCycleRecurse(PGPROC *checkProc, if ((proclock->holdMask & LOCKBIT_ON(lm)) && (conflictMask & LOCKBIT_ON(lm))) { - /* - * Look for a blocking autovacuum. There can be more than - * one in the deadlock cycle, in which case we just pick a - * random one. We stash the autovacuum worker's PGPROC so - * that the caller can send a cancel signal to it, if - * appropriate. - * - * Note we read vacuumFlags without any locking. This is - * OK only for checking the PROC_IS_AUTOVACUUM flag, - * because that flag is set at process start and never - * reset; there is logic elsewhere to avoid canceling an - * autovacuum that is working for preventing Xid - * wraparound problems (which needs to read a different - * vacuumFlag bit), but we don't do that here to avoid - * grabbing ProcArrayLock. - */ - if (pgxact->vacuumFlags & PROC_IS_AUTOVACUUM) - blocking_autovacuum_proc = proc; - /* This proc hard-blocks checkProc */ if (FindLockCycleRecurse(proc, depth + 1, softEdges, nSoftEdges)) @@ -559,7 +540,34 @@ FindLockCycleRecurse(PGPROC *checkProc, return true; } - /* If no deadlock, we're done looking at this proclock */ + + /* + * No deadlock here, but see if this proc is an autovacuum + * that is directly hard-blocking our own proc. If so, + * report it so that the caller can send a cancel signal + * to it, if appropriate. If there's more than one such + * proc, it's indeterminate which one will be reported. + * + * We don't touch autovacuums that are indirectly blocking + * us; it's up to the direct blockee to take action. This + * rule simplifies understanding the behavior and ensures + * that an autovacuum won't be canceled with less than + * deadlock_timeout grace period. + * + * Note we read vacuumFlags without any locking. This is + * OK only for checking the PROC_IS_AUTOVACUUM flag, + * because that flag is set at process start and never + * reset. There is logic elsewhere to avoid canceling an + * autovacuum that is working to prevent XID wraparound + * problems (which needs to read a different vacuumFlag + * bit), but we don't do that here to avoid grabbing + * ProcArrayLock. + */ + if (checkProc == MyProc && + pgxact->vacuumFlags & PROC_IS_AUTOVACUUM) + blocking_autovacuum_proc = proc; + + /* We're done looking at this proclock */ break; } }