Skip to content

Remove coverage badge from README - #9

Merged
TeoSlayer merged 1 commit into
mainfrom
TeoSlayer-patch-1
Feb 27, 2026
Merged

TeoSlayer merged 1 commit into
mainfrom
TeoSlayer-patch-1

Conversation

@TeoSlayer

Copy link
Copy Markdown
Collaborator

No description provided.

@TeoSlayer
TeoSlayer merged commit 4c54cc0 into main Feb 27, 2026
1 check passed
@TeoSlayer
TeoSlayer deleted the TeoSlayer-patch-1 branch March 23, 2026 22:28
TeoSlayer added a commit that referenced this pull request Apr 30, 2026
TeoSlayer pushed a commit that referenced this pull request May 3, 2026
…onn callers

Symptom: iter 4 added a 32 KB cap on per-Connection NagleBuf with
ErrSendBufFull returned to the caller of daemon.SendData. The
per-port services use connAdapter to expose Connections as net.Conn
(so http.ServeConn, io.Copy, gRPC etc. can run unchanged over Pilot
tunnels). connAdapter.Write currently propagates ErrSendBufFull
directly:

  func (a *connAdapter) Write(p []byte) (int, error) {
      if err := a.daemon.SendData(a.conn, p); err != nil {
          return 0, err
      }
      return len(p), nil
  }

This violates the implicit net.Conn contract. Standard-library
callers (net/http, io.Copy, bufio.Writer) treat ANY non-nil Write
error as "connection broken" and abort. A slow peer with a
momentarily full NagleBuf — a transient, recoverable condition —
silently breaks every HTTP/gRPC/stream consumer running on top of
the daemon, manifesting as "connection reset" or "EOF" errors at
the application boundary.

Real-world impact: webhook senders, port-forwarded HTTP servers,
gateway-mode TCP proxying, the dataexchange service all break the
moment a peer's cwnd fills (which iter 4's cap is meant to handle
gracefully — bound memory without dropping data).

Replication (sendbuf_caller_bug_test.go):
  - Build Established Connection
  - Pre-fill NagleBuf to MaxNagleBuf
  - Call connAdapter.Write([]byte("ABC")) and time it
  - assert: returns (0, ErrSendBufFull) within 100ms (current bug)

GREEN flips assertion: Write must block until NagleBuf drains, then
return (3, nil) — matching net.Conn back-pressure semantics that
HTTP/gRPC/io.Copy actually rely on.
TeoSlayer pushed a commit that referenced this pull request May 3, 2026
Bug fixed: connAdapter.Write no longer surfaces ErrSendBufFull as a
fatal connection error to net.Conn callers. It now blocks-and-retries
with capped exponential backoff (5ms → 100ms), surfacing the error
only on (a) connection state moving out of Established, or (b) the
30s connAdapterWriteDeadline elapsing. Net.Conn callers (http,
io.Copy, bufio, gRPC) see Write block briefly under back-pressure
and then succeed — matching the implicit contract that's modelled
on a kernel TCP send buffer being full.

Implementation (pkg/daemon/services.go):

  func (a *connAdapter) Write(p []byte) (int, error) {
      backoff := 5 * time.Millisecond
      const maxBackoff = 100 * time.Millisecond
      deadline := time.Now().Add(connAdapterWriteDeadline)
      for {
          err := a.daemon.SendData(a.conn, p)
          if err == nil { return len(p), nil }
          if !errors.Is(err, ErrSendBufFull) { return 0, err }
          a.conn.Mu.Lock(); st := a.conn.State; a.conn.Mu.Unlock()
          if st != StateEstablished {
              return 0, fmt.Errorf("connection no longer established (state=%v)", st)
          }
          if time.Now().After(deadline) { return 0, err }
          time.Sleep(backoff)
          if backoff < maxBackoff { backoff *= 2 }
      }
  }

Why connAdapterWriteDeadline = 30s: long enough to ride out a
multi-RTT cwnd pause on a slow peer, short enough that a wedged
peer doesn't block the application forever. Future iter could
expose this via SetWriteDeadline, but for now the constant is
sufficient — slow peers eventually drain or the connection tears
down via dead-peer detection (idleSweepLoop, ICMP fast-flip).

Tests:
  - TestConnAdapterWriteSurfacesErrSendBufFullToCaller: with
    NagleBuf pre-filled to MaxNagleBuf, Write blocks; after a
    side goroutine drains NagleBuf, Write returns (3, nil)
    within 500ms. Pre-fix this returned (0, ErrSendBufFull)
    immediately.
  - TestConnAdapterWriteSurfacesNonBufferErrors: a closed conn's
    "connection not established" error propagates immediately
    (not in retry loop). Within 100ms, non-ErrSendBufFull,
    non-nil err.

Race-clean across full pkg/daemon (62s). 14 commits ahead of v1.9.0,
9 bug categories closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant