@@ -1208,13 +1208,23 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
1208
1208
*/
1209
1209
if (log_lock_waits && deadlock_state != DS_NOT_YET_CHECKED )
1210
1210
{
1211
- StringInfoData buf ;
1211
+ StringInfoData buf ,
1212
+ lock_waiters_sbuf ,
1213
+ lock_holders_sbuf ;
1212
1214
const char * modename ;
1213
1215
long secs ;
1214
1216
int usecs ;
1215
1217
long msecs ;
1218
+ SHM_QUEUE * procLocks ;
1219
+ PROCLOCK * proclock ;
1220
+ bool first_holder = true,
1221
+ first_waiter = true;
1222
+ int lockHoldersNum = 0 ;
1216
1223
1217
1224
initStringInfo (& buf );
1225
+ initStringInfo (& lock_waiters_sbuf );
1226
+ initStringInfo (& lock_holders_sbuf );
1227
+
1218
1228
DescribeLockTag (& buf , & locallock -> tag .lock );
1219
1229
modename = GetLockmodeName (locallock -> tag .lock .locktag_lockmethodid ,
1220
1230
lockmode );
@@ -1224,10 +1234,67 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
1224
1234
msecs = secs * 1000 + usecs / 1000 ;
1225
1235
usecs = usecs % 1000 ;
1226
1236
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
+
1227
1291
if (deadlock_state == DS_SOFT_DEADLOCK )
1228
1292
ereport (LOG ,
1229
1293
(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 ))));
1231
1298
else if (deadlock_state == DS_HARD_DEADLOCK )
1232
1299
{
1233
1300
/*
@@ -1239,13 +1306,19 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
1239
1306
*/
1240
1307
ereport (LOG ,
1241
1308
(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 ))));
1243
1313
}
1244
1314
1245
1315
if (myWaitStatus == STATUS_WAITING )
1246
1316
ereport (LOG ,
1247
1317
(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 ))));
1249
1322
else if (myWaitStatus == STATUS_OK )
1250
1323
ereport (LOG ,
1251
1324
(errmsg ("process %d acquired %s on %s after %ld.%03d ms" ,
@@ -1265,7 +1338,10 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
1265
1338
if (deadlock_state != DS_HARD_DEADLOCK )
1266
1339
ereport (LOG ,
1267
1340
(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 ))));
1269
1345
}
1270
1346
1271
1347
/*
@@ -1275,6 +1351,8 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
1275
1351
deadlock_state = DS_NO_DEADLOCK ;
1276
1352
1277
1353
pfree (buf .data );
1354
+ pfree (lock_holders_sbuf .data );
1355
+ pfree (lock_waiters_sbuf .data );
1278
1356
}
1279
1357
} while (myWaitStatus == STATUS_WAITING );
1280
1358
0 commit comments