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 c44b683b11edca99f21bbead013c2052d00a10d2 Author: Andrew Stitcher <[email protected]> AuthorDate: Tue Oct 6 13:27:14 2026 -0400 PROTON-2984: Don't restart an in-flight libuv connect leader_process_pconnection() called leader_connect() on every pass while pc->connected was still 0, including while an outbound connect was already in flight. That re-ran uv_tcp_init() on the live uv_tcp_t, which unconditionally re-initializes its io_watcher; if the loop still had that watcher queued, loop->watcher_queue was left with a self-linked node that uv__queue_remove() can never unlink. uv__io_poll() then spun forever, so the leader thread never returned from uv_run() and never picked up any further proactor state. The other proactor threads stayed parked on pn_proactor_t::cond, hanging the process with one core pegged. Any work_notify() during the connect window triggered it, e.g. pn_connection_wake() from another thread. Start the connect sequence once; retries are already driven by the libuv connect callbacks, and a later pass only needs to deliver pending driver events so that a terminal connect failure is still reported. Reproduced with c-threaderciser, which hung roughly 1 run in 10 before this change and 70 of 70 clean after it. Assisted-By: Claude Opus 5 <[email protected]> --- c/src/proactor/libuv.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/c/src/proactor/libuv.c b/c/src/proactor/libuv.c index 25c5d94ec..e1acdb33d 100644 --- a/c/src/proactor/libuv.c +++ b/c/src/proactor/libuv.c @@ -171,6 +171,7 @@ typedef struct pconnection_t { uv_connect_t connect; /* Outgoing connection only */ int connected; /* 0: not connected, <0: connecting after error, 1 = connected ok */ + bool connect_started; /* Outgoing connect sequence has been started */ lsocket_t *lsocket; /* Incoming connection only */ @@ -910,6 +911,13 @@ static void check_wake(pconnection_t *pc) { static bool leader_process_pconnection(pconnection_t *pc) { /* Important to do the following steps in order */ if (!pc->connected) { + /* Retries are driven by the libuv connect callbacks. Restarting here would + re-run uv_tcp_init() on the live uv_tcp_t, re-initializing its watcher + while the loop still has it queued and corrupting loop->watcher_queue. */ + if (pc->connect_started) { + return pn_connection_driver_has_event(&pc->driver); + } + pc->connect_started = true; return leader_connect(pc); } if (pc->writing) { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
