Skip to content

Commit 15ad6f1

Browse files
committed
When building with LWLOCK_STATS, initialize the stats in LWLockWaitUntilFree.
If LWLockWaitUntilFree was called before the first LWLockAcquire call, you would either crash because of access to uninitialized array or account the acquisition incorrectly. LWLockConditionalAcquire doesn't have this problem because it doesn't update the lwlock stats. In practice, this never happens because there is no codepath where you would call LWLockWaitUntilfree before LWLockAcquire after a new process is launched. But that's just accidental, there's no guarantee that that's always going to be true in the future. Spotted by Jeff Janes.
1 parent 442231d commit 15ad6f1

File tree

1 file changed

+23
-10
lines changed

1 file changed

+23
-10
lines changed

src/backend/storage/lmgr/lwlock.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,22 @@ LOG_LWDEBUG(const char *where, LWLockId lockid, const char *msg)
123123

124124
#ifdef LWLOCK_STATS
125125

126+
static void init_lwlock_stats(void);
127+
static void print_lwlock_stats(int code, Datum arg);
128+
129+
static void
130+
init_lwlock_stats(void)
131+
{
132+
int *LWLockCounter = (int *) ((char *) LWLockArray - 2 * sizeof(int));
133+
int numLocks = LWLockCounter[1];
134+
135+
sh_acquire_counts = calloc(numLocks, sizeof(int));
136+
ex_acquire_counts = calloc(numLocks, sizeof(int));
137+
block_counts = calloc(numLocks, sizeof(int));
138+
counts_for_pid = MyProcPid;
139+
on_shmem_exit(print_lwlock_stats, 0);
140+
}
141+
126142
static void
127143
print_lwlock_stats(int code, Datum arg)
128144
{
@@ -332,16 +348,7 @@ LWLockAcquire(LWLockId lockid, LWLockMode mode)
332348
#ifdef LWLOCK_STATS
333349
/* Set up local count state first time through in a given process */
334350
if (counts_for_pid != MyProcPid)
335-
{
336-
int *LWLockCounter = (int *) ((char *) LWLockArray - 2 * sizeof(int));
337-
int numLocks = LWLockCounter[1];
338-
339-
sh_acquire_counts = calloc(numLocks, sizeof(int));
340-
ex_acquire_counts = calloc(numLocks, sizeof(int));
341-
block_counts = calloc(numLocks, sizeof(int));
342-
counts_for_pid = MyProcPid;
343-
on_shmem_exit(print_lwlock_stats, 0);
344-
}
351+
init_lwlock_stats();
345352
/* Count lock acquisition attempts */
346353
if (mode == LW_EXCLUSIVE)
347354
ex_acquire_counts[lockid]++;
@@ -588,6 +595,12 @@ LWLockWaitUntilFree(LWLockId lockid, LWLockMode mode)
588595

589596
PRINT_LWDEBUG("LWLockWaitUntilFree", lockid, lock);
590597

598+
#ifdef LWLOCK_STATS
599+
/* Set up local count state first time through in a given process */
600+
if (counts_for_pid != MyProcPid)
601+
init_lwlock_stats();
602+
#endif
603+
591604
/* Ensure we will have room to remember the lock */
592605
if (num_held_lwlocks >= MAX_SIMUL_LWLOCKS)
593606
elog(ERROR, "too many LWLocks taken");

0 commit comments

Comments
 (0)