From nobody Mon May 25 15:15:47 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gPKFv4gFjz6f6wv for ; Mon, 25 May 2026 15:15:47 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gPKFv40v1z3lkj for ; Mon, 25 May 2026 15:15:47 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1779722147; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=F/mzrzZZFpnKcYnqTj0CIAH+wF4xA7JLLj5bRFS+tK8=; b=JQkzgoew8qmP83cFeBT0G5DcxrnIDRJ64zIVY6eYH//IH3EmIVz4GHE2uvCUu4rPXxrf+f G1TqqnY3k2x2wU/BVSUbQFL4uSQhY+b22Em4rOOXi53wFYnRLZErPjUBOm180PuSF1xrdA C8UNLt6rPldNaXxZUf0tP00xt6SyYEDBXrrsHQDzfNEdR+8ppSaccU3lpM+ONxpgI5kYYf tO6hLiN23uq01g1NGRBMImymkHymXNbKywBoLwLato+MEcxzLoMbfPfWwBH6y+4UlQoCs2 PHl1FjT4Qxbx4t0jU8qQ8bLCSyuBCuK7d+QZ+TezH3Lhg+SwBCRnwqt0uxKePQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1779722147; a=rsa-sha256; cv=none; b=Y9wc/KBR852NTylt9anwws1JMC6cDHieeZLtH6RODBYrr8vQ+skA6JVm1vdyJwmvUGplrP ikXjWltSGP4ikytaxzJUWUOuY1HUWHEcIWeWvr+3DPd62j9vnWGdLO5rX8KxZbs3H7C0Jd xyRe/2UjSxSKP+nwTSAZR2oB6c5OBAJFWt24cjPxtdivOe41FiFYJJAu8ebOCIL9pZgDw4 O1JJM/40/M9JwqDAuW3sThAAcdJ/0mhmN4UCi+mvv+B2+eFxYtTjuUNDJC0uCRefOHolvf 2utOMQVjMHWoOypbbn9xMBX5Z2EAnXKPnFJvqvrGUby3uhL/22MM7kqDiCxMbg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1779722147; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=F/mzrzZZFpnKcYnqTj0CIAH+wF4xA7JLLj5bRFS+tK8=; b=KHrUpetOoNs9wE1eEMJB9JxcyWsnMMMzHR+9MvtyuEpWbUG8WaX74cAJWYvX7z87+VEahz A5FjKxXdwLevnXZW9vd+pVMrugrbQFYUaC87hgdWfU3dX5z99zrm3RVntyhuNdfEf6uMME a5CzgXtPu5J6LmnFf4u071FFBMxJ9VNbUNVRyXvDdXmhjDYfM3K5nbRQMMvy2nUqS+PYGk qgy7GGPGuruCdAbE96nUFN78KJhtkgKSO0sZADnOgdw6sHNkKT6xF35Vjp1pv3gJVrngpQ 7gpCpIdTLcQHK3mbEWJ7nbbprVAejCTXoacd7Vv65jidgIXseWbYHXKvM9Eq9Q== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gPKFv3cF9zn5l for ; Mon, 25 May 2026 15:15:47 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 2226e by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 25 May 2026 15:15:47 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: bc70af0acdda - stable/15 - eventhandler: Fix a race when pruning eventhandlers List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: bc70af0acdda8e9e2a2b21ccc9870f874d803408 Auto-Submitted: auto-generated Date: Mon, 25 May 2026 15:15:47 +0000 Message-Id: <6a1467a3.2226e.53f7bc19@gitrepo.freebsd.org> The branch stable/15 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=bc70af0acdda8e9e2a2b21ccc9870f874d803408 commit bc70af0acdda8e9e2a2b21ccc9870f874d803408 Author: Mark Johnston AuthorDate: 2026-05-06 11:48:05 +0000 Commit: Mark Johnston CommitDate: 2026-05-25 15:15:39 +0000 eventhandler: Fix a race when pruning eventhandlers By default, eventhandler_deregister() blocks until it reaches some point where no threads are invoking the event. At this point, it knows that 1) no threads are currently executing the handler, 2) some thread has freed the eventhandler structure by virtue of having called eventhandler_prune_list(), so it is safe to return. Suppose a thread is trying to deregister an event handler. A different thread prunes it, and wakes up the first thread. Before the first thread runs, a third thread grabs the event handler lock, and starts executing handlers. The first thread observes el_runcount > 0, and goes back to sleep. The third thread sees no event handlers to prune, and doesn't wake up the first thread, which sleeps forever. This change fixes the race and tries to make eventhandler_invoke() more efficient: keep a count of the number of dead list entries and only prune the list if there is at least one dead entry. Also, in eventhandler_deregister(), we only need to sleep if some dead entries are present, rather than sleeping whenever some thread is running handlers. Reviewed by: kib MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D56767 (cherry picked from commit 735b16d490aee158beb54c415b716475a0d19cda) --- sys/kern/subr_eventhandler.c | 18 ++++++++++++++---- sys/sys/eventhandler.h | 4 ++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/sys/kern/subr_eventhandler.c b/sys/kern/subr_eventhandler.c index 7568101dabd2..e91647648995 100644 --- a/sys/kern/subr_eventhandler.c +++ b/sys/kern/subr_eventhandler.c @@ -198,7 +198,10 @@ _eventhandler_deregister(struct eventhandler_list *list, eventhandler_tag tag, } else { CTR3(KTR_EVH, "%s: marking item %p from \"%s\" as dead", __func__, ep, list->el_name); + KASSERT(ep->ee_priority != EHE_DEAD_PRIORITY, + ("%s: handler for %s is dead", __func__, list->el_name)); ep->ee_priority = EHE_DEAD_PRIORITY; + list->el_deadcount++; } } else { /* remove entire list */ @@ -213,11 +216,15 @@ _eventhandler_deregister(struct eventhandler_list *list, eventhandler_tag tag, } else { CTR2(KTR_EVH, "%s: marking all items from \"%s\" as dead", __func__, list->el_name); - TAILQ_FOREACH(ep, &list->el_entries, ee_link) + TAILQ_FOREACH(ep, &list->el_entries, ee_link) { + KASSERT(ep->ee_priority != EHE_DEAD_PRIORITY, + ("%s: handler for %s is dead", __func__, list->el_name)); ep->ee_priority = EHE_DEAD_PRIORITY; + list->el_deadcount++; + } } } - while (wait && list->el_runcount > 0) + while (wait && list->el_deadcount > 0) mtx_sleep(list, &list->el_lock, 0, "evhrm", 0); EHL_UNLOCK(list); } @@ -292,8 +299,11 @@ eventhandler_prune_list(struct eventhandler_list *list) pruned++; } } - if (pruned > 0) - wakeup(list); + KASSERT(pruned == list->el_deadcount, + ("%s: pruned %u entries from \"%s\" but expected %u", + __func__, pruned, list->el_name, list->el_deadcount)); + list->el_deadcount = 0; + wakeup(list); } /* diff --git a/sys/sys/eventhandler.h b/sys/sys/eventhandler.h index c0d9811dd1b9..2ed71ad1fa98 100644 --- a/sys/sys/eventhandler.h +++ b/sys/sys/eventhandler.h @@ -45,7 +45,7 @@ struct eventhandler_entry_vimage { struct eventhandler_list { char *el_name; - int el_flags; /* Unused. */ + u_int el_deadcount; u_int el_runcount; struct mtx el_lock; TAILQ_ENTRY(eventhandler_list) el_link; @@ -81,7 +81,7 @@ struct eventhandler_list { KASSERT((list)->el_runcount > 0, \ ("eventhandler_invoke: runcount underflow")); \ (list)->el_runcount--; \ - if ((list)->el_runcount == 0) \ + if ((list)->el_runcount == 0 && (list)->el_deadcount != 0) \ eventhandler_prune_list(list); \ EHL_UNLOCK((list)); \ } while (0)