Skip to content

EMFILE crash in connectivity-probe socket creation after long uptime #932

Description

@kasnder

Do you use TrackerControl from Google Play/F-Droid/other?
Unknown (crash report via ACRA, BUILD_CONFIG=N/A)

Describe the bug
After several days of uptime, the app crashes with EMFILE (too many open files) while creating the socket used for the network-validation probe in ServiceSinkhole's connectivity NetworkCallback.

java.io.UncheckedIOException: java.io.IOException: fcntl failed: EMFILE (Too many open files)
	at android.os.ParcelFileDescriptor.fromSocket(ParcelFileDescriptor.java:470)
	at android.net.Network.bindSocket(Network.java:416)
	at android.net.Network$NetworkBoundSocketFactory.createSocket(Network.java:277)
	at eu.faircode.netguard.ServiceSinkhole$7.checkConnectivity(SourceFile:189)
	at eu.faircode.netguard.ServiceSinkhole$7.onAvailable(SourceFile:65)
	at android.net.ConnectivityManager$NetworkCallback.onAvailable(ConnectivityManager.java:4218)
	at android.net.ConnectivityManager$NetworkCallback.onAvailable(ConnectivityManager.java:4188)
	at android.net.ConnectivityManager$CallbackHandler.handleMessage(ConnectivityManager.java:4678)
	at android.os.Handler.dispatchMessage(Handler.java:132)
	at android.os.Looper.dispatchMessage(Looper.java:333)
	at android.os.Looper.loopOnce(Looper.java:263)
	at android.os.Looper.loop(Looper.java:367)
	at android.os.HandlerThread.run(HandlerThread.java:139)
Caused by: java.io.IOException: fcntl failed: EMFILE (Too many open files)
	at android.os.ParcelFileDescriptor.dup(ParcelFileDescriptor.java:377)
	at android.os.ParcelFileDescriptor.fromSocket(ParcelFileDescriptor.java:468)
	... 12 more
Caused by: android.system.ErrnoException: fcntl failed: EMFILE (Too many open files)
	at libcore.io.Linux.fcntlInt(Native Method)
	at libcore.io.ForwardingOs.fcntlInt(ForwardingOs.java:252)
	at libcore.io.ForwardingOs.fcntlInt(ForwardingOs.java:252)
	at android.system.Os.fcntlInt(Os.java:187)
	at android.os.ParcelFileDescriptor.dup(ParcelFileDescriptor.java:373)
	... 13 more

App uptime: started 2026-08-25T21:17:05.641+03:00, crashed 2026-08-30T13:51:11.249+03:00 (~5 days).
Device: Android 16, AVAILABLE_MEM_SIZE=141685964800, TOTAL_MEM_SIZE=241419628544 (plenty of free memory — this is a file-descriptor ceiling, not a memory issue).

Analysis
The socket that fails to open (ServiceSinkhole's networkMonitorCallback.checkConnectivity) is itself closed correctly in a finally block, so it isn't the leak — it's just the allocation that happens to tip the process over its fd limit. The real cause is a slow file-descriptor leak elsewhere in the service that accumulates over long uptimes until any new socket/pipe allocation fails with EMFILE. The most likely source is repeated VPN-interface replacement on network changes (Wi-Fi↔cellular handoffs, DHCP renewals) via VpnReplacementSequencer.replace/stopNative/stopVPN in ServiceSinkhole.java, which is the "ParcelFileDescriptor close race" already noted as a live concern in the project's AGENTS.md.

To Reproduce
Not yet reliably reproducible; requires long uptime with repeated network changes to exhaust the process fd table. Suggest: track open fd count (/proc/<pid>/fd) over time on a device with frequent connectivity changes to confirm the leak source.

Expected behavior
The service should not leak file descriptors across VPN restarts/network changes, and a single failed probe socket allocation should not crash the whole service (the IOException from createSocket()/bindSocket() is presently only caught as part of the try/finally around socket.connect, but createSocket() itself is outside that try block — see ServiceSinkhole.java around the checkConnectivity method).

Crash report metadata

  • STACK_TRACE_HASH: 6c774901
  • REPORT_ID: 094905b7-2e76-464f-b14e-7c7d23996238
  • ANDROID_VERSION: 16

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions