This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/qpid-proton.git
commit 2ffca2d99f80d86eaf6f704141b3ed68d31ec15a Author: Andrew Stitcher <[email protected]> AuthorDate: Tue Oct 6 17:03:21 2026 -0400 PROTON-2986: Don't crash closing a listener that never listened Both libuv and win_iocp proactors would crash if you close a listener that was never added to the proactor, because they would try to access the NULL proactor on closing. Added a test to ensure there is no regression in this behaviour. Assisted-By: Claude Opus 5 <[email protected]> --- c/src/proactor/libuv.c | 5 ++++- c/src/proactor/win_iocp.cpp | 3 +++ c/tests/proactor_test.cpp | 9 +++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/c/src/proactor/libuv.c b/c/src/proactor/libuv.c index 59cd1c653..c12e1d4d8 100644 --- a/c/src/proactor/libuv.c +++ b/c/src/proactor/libuv.c @@ -1367,7 +1367,10 @@ pn_listener_t *pn_listener(void) { void pn_listener_close(pn_listener_t* l) { /* May be called from any thread */ uv_mutex_lock(&l->lock); - listener_close_lh(l); + /* Don't crash if we never passed it to a proactor */ + if (l->work.proactor) { + listener_close_lh(l); + } uv_mutex_unlock(&l->lock); } diff --git a/c/src/proactor/win_iocp.cpp b/c/src/proactor/win_iocp.cpp index 85d5821c5..d64ab0cb7 100644 --- a/c/src/proactor/win_iocp.cpp +++ b/c/src/proactor/win_iocp.cpp @@ -3160,6 +3160,9 @@ static void listener_begin_close(pn_listener_t* l) { void pn_listener_close(pn_listener_t* l) { csguard g(&l->context.cslock); + /* Don't crash if we never passed it to a proactor */ + if (!l->context.proactor) + return; listener_begin_close(l); wakeup(&l->psockets[0]); } diff --git a/c/tests/proactor_test.cpp b/c/tests/proactor_test.cpp index 8c1e4c9d7..8a32f654f 100644 --- a/c/tests/proactor_test.cpp +++ b/c/tests/proactor_test.cpp @@ -194,6 +194,15 @@ TEST_CASE("proactor_connect_close_before_open") { REQUIRE(h.proactor_inactive_); } +/* Close a listener that was never passed to pn_proactor_listen(). Thread safety + is the only documented precondition, so this must not crash. */ +TEST_CASE("proactor_listener_close_before_listen") { + pn_listener_t *l = pn_listener(); + REQUIRE(l != nullptr); + pn_listener_close(l); + pn_listener_free(l); +} + /* Failing name lookup - connect to invalid hostname. */ TEST_CASE("proactor_name_lookup_fails") { common_handler h; --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
