diff -Naurp pcp-5.3.7.orig/src/libpcp_web/src/load.h pcp-5.3.7/src/libpcp_web/src/load.h
--- pcp-5.3.7.orig/src/libpcp_web/src/load.h	2021-02-17 15:27:41.000000000 +1100
+++ pcp-5.3.7/src/libpcp_web/src/load.h	2024-09-09 13:45:56.531933622 +1000
@@ -42,8 +42,9 @@ typedef struct context {
     unsigned int	setup	: 1;	/* context established */
     unsigned int	cached	: 1;	/* context/source in cache */
     unsigned int	garbage	: 1;	/* context pending removal */
+    unsigned int	inactive: 1;	/* context removal deferred */
     unsigned int	updated : 1;	/* context labels are updated */
-    unsigned int	padding : 4;	/* zero-filled struct padding */
+    unsigned int	padding : 3;	/* zero-filled struct padding */
     unsigned int	refcount : 16;	/* currently-referenced counter */
     unsigned int	timeout;	/* context timeout in milliseconds */
     uv_timer_t		timer;
diff -Naurp pcp-5.3.7.orig/src/libpcp_web/src/webgroup.c pcp-5.3.7/src/libpcp_web/src/webgroup.c
--- pcp-5.3.7.orig/src/libpcp_web/src/webgroup.c	2024-09-09 13:44:34.166748200 +1000
+++ pcp-5.3.7/src/libpcp_web/src/webgroup.c	2024-09-09 13:45:56.531933622 +1000
@@ -134,9 +134,18 @@ webgroup_timeout_context(uv_timer_t *arg
      * is returned to zero by the caller, or background cleanup
      * finds this context and cleans it.
      */
-    if (cp->refcount == 0 && cp->garbage == 0) {
-	cp->garbage = 1;
-	uv_timer_stop(&cp->timer);
+    if (cp->refcount == 0) {
+	if (cp->garbage == 0) {
+	    cp->garbage = 1;
+	    uv_timer_stop(&cp->timer);
+	}
+    } else {
+	/*
+	 * Context timed out but still referenced, must wait
+	 * until the caller releases its reference (shortly)
+	 * before beginning garbage collection process.
+	 */
+	cp->inactive = 1;
     }
 }
 
@@ -298,20 +307,28 @@ webgroup_garbage_collect(struct webgroup
     dictIterator        *iterator;
     dictEntry           *entry;
     context_t		*cp;
-    unsigned int	count = 0, drops = 0;
+    unsigned int	count = 0, drops = 0, garbageset = 0, inactiveset = 0;
 
     if (pmDebugOptions.http || pmDebugOptions.libweb)
-	fprintf(stderr, "%s: started\n", "webgroup_garbage_collect");
+	fprintf(stderr, "%s: started for groups %p\n",
+			"webgroup_garbage_collect", groups);
 
     /* do context GC if we get the lock (else don't block here) */
     if (uv_mutex_trylock(&groups->mutex) == 0) {
 	iterator = dictGetSafeIterator(groups->contexts);
 	for (entry = dictNext(iterator); entry;) {
 	    cp = (context_t *)dictGetVal(entry);
+	    if (cp->privdata != groups)
+		continue;
 	    entry = dictNext(iterator);
-	    if (cp->garbage && cp->privdata == groups) {
+	    if (cp->garbage)
+		garbageset++;
+	    if (cp->inactive && cp->refcount == 0)
+		inactiveset++;
+	    if (cp->garbage || (cp->inactive && cp->refcount == 0)) {
 		if (pmDebugOptions.http || pmDebugOptions.libweb)
-		    fprintf(stderr, "GC context %u (%p)\n", cp->randomid, cp);
+		    fprintf(stderr, "GC dropping context %u (%p)\n",
+				    cp->randomid, cp);
 		uv_mutex_unlock(&groups->mutex);
 		webgroup_drop_context(cp, groups);
 		uv_mutex_lock(&groups->mutex);
@@ -324,7 +341,8 @@ webgroup_garbage_collect(struct webgroup
 	/* if dropping the last remaining context, do cleanup */
 	if (groups->active && drops == count) {
 	    if (pmDebugOptions.http || pmDebugOptions.libweb)
-		fprintf(stderr, "%s: freezing\n", "webgroup_garbage_collect");
+		fprintf(stderr, "%s: freezing groups %p\n",
+				"webgroup_garbage_collect", groups);
 	    webgroup_timers_stop(groups);
 	}
 	uv_mutex_unlock(&groups->mutex);
@@ -334,8 +352,10 @@ webgroup_garbage_collect(struct webgroup
     mmv_set(groups->map, groups->metrics[WEBGROUP_GC_COUNT], &count);
 
     if (pmDebugOptions.http || pmDebugOptions.libweb)
-	fprintf(stderr, "%s: finished [%u drops from %u entries]\n",
-			"webgroup_garbage_collect", drops, count);
+	fprintf(stderr, "%s: finished [%u drops from %u entries,"
+			" %u garbageset, %u inactiveset]\n",
+			"webgroup_garbage_collect", drops, count,
+			garbageset, inactiveset);
 }
 
 static void
@@ -354,7 +374,7 @@ webgroup_use_context(struct context *cp,
     int			sts;
     struct webgroups    *gp = (struct webgroups *)cp->privdata;
 
-    if (cp->garbage == 0) {
+    if (cp->garbage == 0 && cp->inactive == 0) {
 	if (cp->setup == 0) {
 	    if ((sts = pmReconnectContext(cp->context)) < 0) {
 		infofmt(*message, "cannot reconnect context: %s",
@@ -424,7 +444,7 @@ webgroup_lookup_context(pmWebGroupSettin
 	    *status = -ENOTCONN;
 	    return NULL;
 	}
-	if (cp->garbage == 0) {
+	if (cp->garbage == 0 && cp->inactive == 0) {
 	    access.username = cp->username;
 	    access.password = cp->password;
 	    access.realm = cp->realm;
