Skip to content

fix(proxy): retry with backoff on transient accept errors instead of exiting#2369

Open
politerealism wants to merge 2 commits into
NVIDIA:mainfrom
politerealism:fix/proxy-accept-retry
Open

fix(proxy): retry with backoff on transient accept errors instead of exiting#2369
politerealism wants to merge 2 commits into
NVIDIA:mainfrom
politerealism:fix/proxy-accept-retry

Conversation

@politerealism

@politerealism politerealism commented Jul 20, 2026

Copy link
Copy Markdown

Summary

  • Replace the unconditional break in the proxy accept loop with a sleep-and-continue pattern so transient errors (EMFILE, ENFILE, etc.) no longer permanently kill the proxy
  • EMFILE/ENFILE errors get exponential backoff (100ms → 5s) to let file descriptors drain; all other accept errors get a fixed 100ms backoff matching existing metadata_server and edge_tunnel patterns
  • OCSF severity raised from Low to Medium for FD exhaustion errors; log messages now include the retry delay

Related Issue

Closes #2337

Changes

crates/openshell-supervisor-network/src/proxy.rs

  • Replaced break on accept error with tokio::time::sleep(backoff).await
  • Added FD exhaustion detection via raw_os_error() (EMFILE=24, ENFILE=23)
  • Added exponential backoff counter that resets on successful accept
  • Updated OCSF event message to include retry delay

Testing

Checklist

  • Conventional commit format
  • Signed-off for DCO compliance
  • No secrets or credentials included
  • Scoped to the issue at hand

Note: This is step 1 of the fix for #2337. Step 2 is PR #2370 (terminate sandbox when the proxy dies unexpectedly).

…exiting

The proxy accept loop unconditionally broke on any accept() error,
permanently killing the proxy while the sandbox continued to report
Ready. Replace the break with a sleep-and-continue pattern: EMFILE/ENFILE
errors get exponential backoff (100ms to 3.2s) to let file descriptors
drain, and all other accept errors get a fixed 100ms backoff matching
the existing metadata_server and edge_tunnel patterns.

Closes NVIDIA#2337

Signed-off-by: Sean Burdine <sburdine@nvidia.com>
Signed-off-by: politerealism <burdcat17@gmail.com>
@copy-pr-bot

copy-pr-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@maxamillion

Copy link
Copy Markdown
Collaborator

/ok to test 8d0099f

- Use libc::EMFILE / libc::ENFILE instead of raw errno values; promote
  libc from dev-dependency to regular dependency
- Extract accept_backoff() and is_fd_exhaustion_error() into testable
  helpers
- Fix unreachable 5s cap: bump exponent limit from min(6) to min(7) so
  the 5_000ms ceiling is reachable (100 * 2^6 = 6400, capped to 5000)
- Add 6 unit tests covering exponential progression, counter reset,
  saturation at cap, EMFILE/ENFILE detection, and non-FD error rejection

Signed-off-by: Sean Burdine <sburdine@nvidia.com>
Signed-off-by: politerealism <burdcat17@gmail.com>
@politerealism

Copy link
Copy Markdown
Author

Follow-up filed: #2372 — the SSH server accept loop (ssh.rs:141) has the same terminate-on-transient-error vulnerability this PR fixes in the proxy. Since the proxy and SSH server share the supervisor's FD table, the same FD pressure can kill the SSH accept loop even while the proxy recovers via backoff. The fix pattern from this PR (retry with backoff) should be applied there as well.

@johntmyers johntmyers self-assigned this Jul 21, 2026
@johntmyers johntmyers added the gator:in-review Gator is reviewing or awaiting PR review feedback label Jul 21, 2026

@johntmyers johntmyers left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gator-agent

PR Review Status

Validation: This is a concentrated network-supervisor fix for the reproducible, linked bug in #2337.
Head SHA: 629fd7d4cef2348aea55394598c47d2600df1ccc

Review findings:

  • Warning — missing regression coverage: The new unit tests cover errno classification and backoff arithmetic, but they never execute the accept loop or prove that it accepts a new connection after EMFILE/ENFILE pressure clears. Please add an isolated Unix subprocess/integration test that lowers RLIMIT_NOFILE, induces the accept failure, releases a descriptor, and verifies a subsequent proxied connection succeeds. Subprocess isolation avoids changing the test runner's process-wide limit.
  • See the inline warning about distinguishing terminal listener errors from retryable failures.

Thanks @politerealism, I also checked the SSH accept-loop gap you called out in #2372. That is appropriately tracked as separate follow-up work and does not expand or block this focused proxy fix.

Docs: Fern docs are not needed because this changes internal recovery and operational logging, not a user-facing command, configuration, API, or workflow.

Next state: gator:in-review while these findings await an author update. The sandbox-network scope will require test:e2e after review feedback is resolved.

let (severity, backoff) = if is_fd_exhaustion {
consecutive_fd_errors = consecutive_fd_errors.saturating_add(1);
(SeverityId::Medium, accept_backoff(consecutive_fd_errors))
} else {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gator-agent

Warning: Retrying every non-FD error indefinitely also catches terminal listener failures such as EBADF, EINVAL, and ENOTSOCK. This leaves ProxyHandle.join alive while the proxy is permanently unusable, preventing supervisor monitoring such as #2370 from observing task termination (CWE-755). Retry known transient errors; emit the failure and exit for terminal errors, or place a bounded retry limit on unknown errors.

@politerealism
politerealism requested a review from johntmyers July 21, 2026 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gator:in-review Gator is reviewing or awaiting PR review feedback

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(proxy): EMFILE stops the sandbox proxy while phase remains Ready

3 participants