From nobody Wed May 06 12:48:02 2026 X-Original-To: dev-commits-src-main@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 4g9ZtC09zCz6cJfb for ; Wed, 06 May 2026 12:48:03 +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 4g9ZtB6hZQz42P2 for ; Wed, 06 May 2026 12:48:02 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1778071682; 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=H/Za06wX1udosAb3tQ/eqGOElF9RqqjwAJ99jcQpYVQ=; b=Z0G53FfNHIVN/bitFa3vyxWudAzIbXcsEDSUj0uNkqxWapCjDYN5048HaxywBipgtXxPTr /Hw3IV6YsTKKwzQ9tYEZBMGDOGfGQioM/+YSPLpZ09jN2vPkt+sn/6kbCQySBeDGZ+ZRG9 8mhl3GPItlHjuKemvH8Nr+bJn8zaFbLn7RiIZys8DN9Tq8NiUPNUoG5KCvzJpJLQ7dYquu on/RIb4UBS+fiBwraYN7CvZrd8sWIx1fgVaoeOliutA78sYWET9LDObXKZDL54ibGmN6Bt 6AgNlY88vCPEgxDJEmunwtu3N2oRnhvDcfsFa9CagXzKw3XcQbVxtXouyjv4FQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1778071682; a=rsa-sha256; cv=none; b=vdQmssBWWLGt/2OkY/QdpVrBQ99io2xBWpTba6dp1gvClLgJz3XDhvBBNr7TpHP41CjfVF wUh17rMzZPTeL3PKM766WJVVhxv9pfUzIrtw5iP+E15e9MCEVhZYIY0ysIn5IaRZCXu4U1 k33Nw8IvK9YU6tDYzhAIgght12YEjDNlS5SweSYlVRjjFFMeFTXL2aZdhrsYyUkZ7CFUJr lceDF8DYUAhAPohtNK/XKlV1QgNO/NGj3SxVk/McTHGjDE1LSHZYT2gjLBo9d65O+44lFD 6D/x2DAwhQNXTICocBEQiM4zbTm9MzpKyX8XsHbASIe3llZdthPMSta93hyvfw== 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=1778071682; 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=H/Za06wX1udosAb3tQ/eqGOElF9RqqjwAJ99jcQpYVQ=; b=sr23Ek5BODfmQ/I9Fq15HfTBnRH/DUy6iCNGugbV2XHhiihEMth42OUiVpf+18MzCcd9Nt MwvA/k1or/TpZzF1KFbfNg7ilj5RlGPVvkWt1JeqyP+7FFzFvfgoDsdesNzn4dJQWW5AaW Ph0QpiPavJlqprfaTPBrkdERBrFdt4VeO/BZtM+8vxTnwh0MOghgRYtamoeO4LbW6om4Zh 0ZlbJTsT3pHMFKfLr9Z7fEvYADkjOleySccNjmshWMLiBAAoS/e4odBXPHpnHcu/+nTRgy z3NP7ON4uoFNiMmXSZay1GujNixOMwsmb7/IonWfastznsfp0oUxL+LYQdZc/A== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4g9ZtB5xzGzgT6 for ; Wed, 06 May 2026 12:48:02 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3df15 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 06 May 2026 12:48:02 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Mark Johnston Subject: git: 735b16d490ae - main - eventhandler: Fix a race when pruning eventhandlers List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@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/main X-Git-Reftype: branch X-Git-Commit: 735b16d490aee158beb54c415b716475a0d19cda Auto-Submitted: auto-generated Date: Wed, 06 May 2026 12:48:02 +0000 Message-Id: <69fb3882.3df15.6f5b09b7@gitrepo.freebsd.org> The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=735b16d490aee158beb54c415b716475a0d19cda commit 735b16d490aee158beb54c415b716475a0d19cda Author: Mark Johnston AuthorDate: 2026-05-06 11:48:05 +0000 Commit: Mark Johnston CommitDate: 2026-05-06 11:48:05 +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 --- 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 29a16b393b52..f37b1150a7e8 100644 --- a/sys/sys/eventhandler.h +++ b/sys/sys/eventhandler.h @@ -46,7 +46,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; @@ -82,7 +82,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)