Anonymous avatar Anonymous committed 15ad6f1

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.

Comments (0)

Files changed (1)

src/backend/storage/lmgr/lwlock.c

 
 #ifdef LWLOCK_STATS
 
+static void init_lwlock_stats(void);
+static void print_lwlock_stats(int code, Datum arg);
+
+static void
+init_lwlock_stats(void)
+{
+	int		   *LWLockCounter = (int *) ((char *) LWLockArray - 2 * sizeof(int));
+	int			numLocks = LWLockCounter[1];
+
+	sh_acquire_counts = calloc(numLocks, sizeof(int));
+	ex_acquire_counts = calloc(numLocks, sizeof(int));
+	block_counts = calloc(numLocks, sizeof(int));
+	counts_for_pid = MyProcPid;
+	on_shmem_exit(print_lwlock_stats, 0);
+}
+
 static void
 print_lwlock_stats(int code, Datum arg)
 {
 #ifdef LWLOCK_STATS
 	/* Set up local count state first time through in a given process */
 	if (counts_for_pid != MyProcPid)
-	{
-		int		   *LWLockCounter = (int *) ((char *) LWLockArray - 2 * sizeof(int));
-		int			numLocks = LWLockCounter[1];
-
-		sh_acquire_counts = calloc(numLocks, sizeof(int));
-		ex_acquire_counts = calloc(numLocks, sizeof(int));
-		block_counts = calloc(numLocks, sizeof(int));
-		counts_for_pid = MyProcPid;
-		on_shmem_exit(print_lwlock_stats, 0);
-	}
+		init_lwlock_stats();
 	/* Count lock acquisition attempts */
 	if (mode == LW_EXCLUSIVE)
 		ex_acquire_counts[lockid]++;
 
 	PRINT_LWDEBUG("LWLockWaitUntilFree", lockid, lock);
 
+#ifdef LWLOCK_STATS
+	/* Set up local count state first time through in a given process */
+	if (counts_for_pid != MyProcPid)
+		init_lwlock_stats();
+#endif
+
 	/* Ensure we will have room to remember the lock */
 	if (num_held_lwlocks >= MAX_SIMUL_LWLOCKS)
 		elog(ERROR, "too many LWLocks taken");
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.