From nobody Fri May 29 20:57:41 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 4gRwfZ05s6z6g5sC for ; Fri, 29 May 2026 20:57:42 +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 4gRwfY5T4bz44Mj for ; Fri, 29 May 2026 20:57:41 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1780088261; 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=n/kSZAM/W3C0wk8a6tSqVcxAkOpSaL2qNbI/P/nNmnE=; b=GPog1lavvQqUdENLRD1p2y54Nn+wCfuZwxy1m93JCx9rloL+/WxAhij6eJGtc4Pp3xK05k Zs7Qeq2M9lNUnN0mk8Z1BLf5pfulj1qkWRPyWXJPFki8T8e+XMn0OlihEOjY/x6z9EfNFG nzNF2NjANDxzPRIn8lJocvmtMmzlleoBlIfbNRAi0xw50n7iuCp8Oc6Npn/I2tJ/kLKCbY lZl0nPc9br2jQ6TgL6J8plsGZW+5UkG1uROMT7+Mh53UcllfJ9k1wkBkL0btnrDp8JabsB DDavXf3JJ3OI1sEVA2cBjiaY6uW4ZazMjjqqYKJaSLPafGciGi22jP6s0Zk8cw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1780088261; a=rsa-sha256; cv=none; b=MEjKF6UaGQCSEy9K7M/D8qZKPnqyPfQgdHKSmksgLmx45LnD5cgic9721J5aEvzLGsRWiM 22gJ79Y6PQTBx/KA963CvZyjKl/DTcNNmfSuXyTlM37UGdAkwN8tg39mGro9ahOp1/o9b4 efjw9IZmrBbijNysFC0hH8qgahlqqWnSf45svhwpneACkDB5iJHg5GhWy35d+xVRI5fSnh IJ4IfTdnudD4IRzxiVrEr+RzlnBIb7DIW/F4PPPqegrUs72icccAR+k4MnN2dQwzjGexoV 9W1UlrScNRiXh0yl8sITNwdPIfzIbeYeA8bYbsql+h046gLl1S/zjSOTsdP+rg== 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=1780088261; 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=n/kSZAM/W3C0wk8a6tSqVcxAkOpSaL2qNbI/P/nNmnE=; b=HGdsFsy9V2ggrhZtVc2q3sgGCwxAL+FLrbK71SGhnXbo6ucbKngQy+zjefUFJRu7AlXQmb UPISiYCYGuT2SiALrFkjkTAsi79TtC1uf8q95EAb+93iPQffZjznnL+S1JtLv3cQ3i29xg 7hi/HyKYoktA0fuwAJbPgjJxdBCt8iChDg+EEOSSYILFSbtmp9pqt5A55T2ZGFgRWo7tNt M6DWcwvD/Hg8eZnUFYyPZj3m8wLpieZE/N7Nb2wAq3Busci0IvxEQsbx9qe/m6IrlUPBa+ 9Cl8yWLrB1NPV7tNgwYCUM2TZH8EiG4dC0RLeHDh6gDzD3MU3m2rWg1j91qCMQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gRwfY51s8zpyK for ; Fri, 29 May 2026 20:57:41 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3460f by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 29 May 2026 20:57:41 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: 4a875b186e8d - stable/14 - 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/14 X-Git-Reftype: branch X-Git-Commit: 4a875b186e8d53e38f79a9e4c0e9ed8949e38ed7 Auto-Submitted: auto-generated Date: Fri, 29 May 2026 20:57:41 +0000 Message-Id: <6a19fdc5.3460f.f44f774@gitrepo.freebsd.org> The branch stable/14 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=4a875b186e8d53e38f79a9e4c0e9ed8949e38ed7 commit 4a875b186e8d53e38f79a9e4c0e9ed8949e38ed7 Author: Mark Johnston AuthorDate: 2026-05-06 11:48:05 +0000 Commit: Mark Johnston CommitDate: 2026-05-29 19:44:43 +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 5a5365d0be6e..ccbb07b826b8 100644 --- a/sys/kern/subr_eventhandler.c +++ b/sys/kern/subr_eventhandler.c @@ -199,7 +199,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 */ @@ -214,11 +217,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); } @@ -293,8 +300,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 47024ecf87a9..be1b04606320 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)