Skip to content

Back off connectivity probes under descriptor exhaustion - #996

Closed
kasnder wants to merge 1 commit into
masterfrom
codex/932-probe-resource-exhaustion
Closed

kasnder wants to merge 1 commit into
masterfrom
codex/932-probe-resource-exhaustion

Conversation

@kasnder

@kasnder kasnder commented Oct 23, 2026

Copy link
Copy Markdown
Member

When a connectivity probe encounters descriptor exhaustion, subsequent network callbacks can keep attempting probes without recording the failure: Android can wrap EMFILE in UncheckedIOException, bypassing the existing handler.

This change recognises EMFILE and ENFILE in checked and unchecked I/O exception chains and pauses optional probes across all networks for ten minutes. The cooldown survives service recreation within the process, is checked again inside queued work, and defers retries while the screen is off. A successful probe after the cooldown restores normal behaviour; ordinary connectivity failures retain their existing per-network backoff. Already-running probes are not cancelled. No timer or VPN/process restart is introduced; retries depend on subsequent network callbacks.

Once per cooldown, after closing any returned probe socket, log a best-effort descriptor census: total count and aggregate types for at most 256 descriptors. Targets, filenames, destinations and descriptor identifiers are omitted. The snapshot is not atomic or representative of every descriptor type; /proc/self/fd may itself be unavailable under exhaustion, in which case that is reported without retrying. Socket counts are not active connection counts.

This mitigates repeated optional work and improves diagnostics; it does not release the resources responsible for exhaustion or establish the cause. Other allocations can still fail. Issue #932 should remain open pending diagnosis.

Validation:

  • :app:testGithubDebugUnitTest --tests eu.faircode.netguard.ProbeResourceGuardTest --tests eu.faircode.netguard.ServiceSinkholeValidationBackoffTest: 11 tests passed.
  • :app:lintGithubDebug: passed.
  • git diff --check: passed.
  • No physical-device exhaustion or long-uptime reproduction. Tests cover policy, exception classification and aggregate diagnostics, not end-to-end framework socket allocation.

Related to #932.

@kasnder kasnder closed this Oct 25, 2026
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