@@ -1208,13 +1208,23 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
12081208 */
12091209 if (log_lock_waits && deadlock_state != DS_NOT_YET_CHECKED )
12101210 {
1211- StringInfoData buf ;
1211+ StringInfoData buf ,
1212+ lock_waiters_sbuf ,
1213+ lock_holders_sbuf ;
12121214 const char * modename ;
12131215 long secs ;
12141216 int usecs ;
12151217 long msecs ;
1218+ SHM_QUEUE * procLocks ;
1219+ PROCLOCK * proclock ;
1220+ bool first_holder = true,
1221+ first_waiter = true;
1222+ int lockHoldersNum = 0 ;
12161223
12171224 initStringInfo (& buf );
1225+ initStringInfo (& lock_waiters_sbuf );
1226+ initStringInfo (& lock_holders_sbuf );
1227+
12181228 DescribeLockTag (& buf , & locallock -> tag .lock );
12191229 modename = GetLockmodeName (locallock -> tag .lock .locktag_lockmethodid ,
12201230 lockmode );
@@ -1224,10 +1234,67 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
12241234 msecs = secs * 1000 + usecs / 1000 ;
12251235 usecs = usecs % 1000 ;
12261236
1237+ /*
1238+ * we loop over the lock's procLocks to gather a list of all
1239+ * holders and waiters. Thus we will be able to provide more
1240+ * detailed information for lock debugging purposes.
1241+ *
1242+ * lock->procLocks contains all processes which hold or wait for
1243+ * this lock.
1244+ */
1245+
1246+ LWLockAcquire (partitionLock , LW_SHARED );
1247+
1248+ procLocks = & (lock -> procLocks );
1249+ proclock = (PROCLOCK * ) SHMQueueNext (procLocks , procLocks ,
1250+ offsetof(PROCLOCK , lockLink ));
1251+
1252+ while (proclock )
1253+ {
1254+ /*
1255+ * we are a waiter if myProc->waitProcLock == proclock; we are
1256+ * a holder if it is NULL or something different
1257+ */
1258+ if (proclock -> tag .myProc -> waitProcLock == proclock )
1259+ {
1260+ if (first_waiter )
1261+ {
1262+ appendStringInfo (& lock_waiters_sbuf , "%d" ,
1263+ proclock -> tag .myProc -> pid );
1264+ first_waiter = false;
1265+ }
1266+ else
1267+ appendStringInfo (& lock_waiters_sbuf , ", %d" ,
1268+ proclock -> tag .myProc -> pid );
1269+ }
1270+ else
1271+ {
1272+ if (first_holder )
1273+ {
1274+ appendStringInfo (& lock_holders_sbuf , "%d" ,
1275+ proclock -> tag .myProc -> pid );
1276+ first_holder = false;
1277+ }
1278+ else
1279+ appendStringInfo (& lock_holders_sbuf , ", %d" ,
1280+ proclock -> tag .myProc -> pid );
1281+
1282+ lockHoldersNum ++ ;
1283+ }
1284+
1285+ proclock = (PROCLOCK * ) SHMQueueNext (procLocks , & proclock -> lockLink ,
1286+ offsetof(PROCLOCK , lockLink ));
1287+ }
1288+
1289+ LWLockRelease (partitionLock );
1290+
12271291 if (deadlock_state == DS_SOFT_DEADLOCK )
12281292 ereport (LOG ,
12291293 (errmsg ("process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms" ,
1230- MyProcPid , modename , buf .data , msecs , usecs )));
1294+ MyProcPid , modename , buf .data , msecs , usecs ),
1295+ (errdetail_log_plural ("Process holding the lock: %s. Wait queue: %s." ,
1296+ "Processes holding the lock: %s. Wait queue: %s." ,
1297+ lockHoldersNum , lock_holders_sbuf .data , lock_waiters_sbuf .data ))));
12311298 else if (deadlock_state == DS_HARD_DEADLOCK )
12321299 {
12331300 /*
@@ -1239,13 +1306,19 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
12391306 */
12401307 ereport (LOG ,
12411308 (errmsg ("process %d detected deadlock while waiting for %s on %s after %ld.%03d ms" ,
1242- MyProcPid , modename , buf .data , msecs , usecs )));
1309+ MyProcPid , modename , buf .data , msecs , usecs ),
1310+ (errdetail_log_plural ("Process holding the lock: %s. Wait queue: %s." ,
1311+ "Processes holding the lock: %s. Wait queue: %s." ,
1312+ lockHoldersNum , lock_holders_sbuf .data , lock_waiters_sbuf .data ))));
12431313 }
12441314
12451315 if (myWaitStatus == STATUS_WAITING )
12461316 ereport (LOG ,
12471317 (errmsg ("process %d still waiting for %s on %s after %ld.%03d ms" ,
1248- MyProcPid , modename , buf .data , msecs , usecs )));
1318+ MyProcPid , modename , buf .data , msecs , usecs ),
1319+ (errdetail_log_plural ("Process holding the lock: %s. Wait queue: %s." ,
1320+ "Processes holding the lock: %s. Wait queue: %s." ,
1321+ lockHoldersNum , lock_holders_sbuf .data , lock_waiters_sbuf .data ))));
12491322 else if (myWaitStatus == STATUS_OK )
12501323 ereport (LOG ,
12511324 (errmsg ("process %d acquired %s on %s after %ld.%03d ms" ,
@@ -1265,7 +1338,10 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
12651338 if (deadlock_state != DS_HARD_DEADLOCK )
12661339 ereport (LOG ,
12671340 (errmsg ("process %d failed to acquire %s on %s after %ld.%03d ms" ,
1268- MyProcPid , modename , buf .data , msecs , usecs )));
1341+ MyProcPid , modename , buf .data , msecs , usecs ),
1342+ (errdetail_log_plural ("Process holding the lock: %s. Wait queue: %s." ,
1343+ "Processes holding the lock: %s. Wait queue: %s." ,
1344+ lockHoldersNum , lock_holders_sbuf .data , lock_waiters_sbuf .data ))));
12691345 }
12701346
12711347 /*
@@ -1275,6 +1351,8 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
12751351 deadlock_state = DS_NO_DEADLOCK ;
12761352
12771353 pfree (buf .data );
1354+ pfree (lock_holders_sbuf .data );
1355+ pfree (lock_waiters_sbuf .data );
12781356 }
12791357 } while (myWaitStatus == STATUS_WAITING );
12801358
0 commit comments