Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 450c823

Browse files
committed
Don't hold ProcArrayLock longer than needed in rare cases
While cancelling an autovacuum worker, we hold ProcArrayLock while formatting a debugging log string. We can make this shorter by saving the data we need to produce the message and doing the formatting outside the locked region. This isn't terribly critical, as it only occurs pretty rarely: when a backend runs deadlock detection and it happens to be blocked by a autovacuum running autovacuum. Still, there's no need to cause a hiccup in ProcArrayLock processing, which can be very high-traffic in some cases. While at it, rework code so that we only print the string when it is really going to be used, as suggested by Michael Paquier. Discussion: https://postgr.es/m/20201118214127.GA3179@alvherre.pgsql Reviewed-by: Michael Paquier <michael@paquier.xyz>
1 parent 0cc9932 commit 450c823

File tree

1 file changed

+22
-13
lines changed
  • src/backend/storage/lmgr

1 file changed

+22
-13
lines changed

src/backend/storage/lmgr/proc.c

+22-13
Original file line numberDiff line numberDiff line change
@@ -1311,40 +1311,54 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
13111311
{
13121312
PGPROC *autovac = GetBlockingAutoVacuumPgproc();
13131313
uint8 statusFlags;
1314+
uint8 lockmethod_copy;
1315+
LOCKTAG locktag_copy;
13141316

1317+
/*
1318+
* Grab info we need, then release lock immediately. Note this
1319+
* coding means that there is a tiny chance that the process
1320+
* terminates its current transaction and starts a different one
1321+
* before we have a change to send the signal; the worst possible
1322+
* consequence is that a for-wraparound vacuum is cancelled. But
1323+
* that could happen in any case unless we were to do kill() with
1324+
* the lock held, which is much more undesirable.
1325+
*/
13151326
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1327+
statusFlags = ProcGlobal->statusFlags[autovac->pgxactoff];
1328+
lockmethod_copy = lock->tag.locktag_lockmethodid;
1329+
locktag_copy = lock->tag;
1330+
LWLockRelease(ProcArrayLock);
13161331

13171332
/*
13181333
* Only do it if the worker is not working to protect against Xid
13191334
* wraparound.
13201335
*/
1321-
statusFlags = ProcGlobal->statusFlags[autovac->pgxactoff];
13221336
if ((statusFlags & PROC_IS_AUTOVACUUM) &&
13231337
!(statusFlags & PROC_VACUUM_FOR_WRAPAROUND))
13241338
{
13251339
int pid = autovac->pid;
13261340
StringInfoData locktagbuf;
13271341
StringInfoData logbuf; /* errdetail for server log */
13281342

1343+
/* report the case, if configured to do so */
13291344
initStringInfo(&locktagbuf);
13301345
initStringInfo(&logbuf);
1331-
DescribeLockTag(&locktagbuf, &lock->tag);
1346+
DescribeLockTag(&locktagbuf, &locktag_copy);
13321347
appendStringInfo(&logbuf,
13331348
_("Process %d waits for %s on %s."),
13341349
MyProcPid,
1335-
GetLockmodeName(lock->tag.locktag_lockmethodid,
1336-
lockmode),
1350+
GetLockmodeName(lockmethod_copy, lockmode),
13371351
locktagbuf.data);
13381352

1339-
/* release lock as quickly as possible */
1340-
LWLockRelease(ProcArrayLock);
1341-
1342-
/* send the autovacuum worker Back to Old Kent Road */
13431353
ereport(DEBUG1,
13441354
(errmsg("sending cancel to blocking autovacuum PID %d",
13451355
pid),
13461356
errdetail_log("%s", logbuf.data)));
13471357

1358+
pfree(logbuf.data);
1359+
pfree(locktagbuf.data);
1360+
1361+
/* send the autovacuum worker Back to Old Kent Road */
13481362
if (kill(pid, SIGINT) < 0)
13491363
{
13501364
/*
@@ -1362,12 +1376,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
13621376
(errmsg("could not send signal to process %d: %m",
13631377
pid)));
13641378
}
1365-
1366-
pfree(logbuf.data);
1367-
pfree(locktagbuf.data);
13681379
}
1369-
else
1370-
LWLockRelease(ProcArrayLock);
13711380

13721381
/* prevent signal from being sent again more than once */
13731382
allow_autovacuum_cancel = false;

0 commit comments

Comments
 (0)