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
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 inServiceSinkhole's connectivityNetworkCallback.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'snetworkMonitorCallback.checkConnectivity) is itself closed correctly in afinallyblock, 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 withEMFILE. The most likely source is repeated VPN-interface replacement on network changes (Wi-Fi↔cellular handoffs, DHCP renewals) viaVpnReplacementSequencer.replace/stopNative/stopVPNinServiceSinkhole.java, which is the "ParcelFileDescriptor close race" already noted as a live concern in the project'sAGENTS.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
IOExceptionfromcreateSocket()/bindSocket()is presently only caught as part of the try/finally aroundsocket.connect, butcreateSocket()itself is outside that try block — seeServiceSinkhole.javaaround thecheckConnectivitymethod).Crash report metadata
STACK_TRACE_HASH:6c774901REPORT_ID:094905b7-2e76-464f-b14e-7c7d23996238ANDROID_VERSION: 16