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]

Reply via email to