summaryrefslogtreecommitdiff
path: root/services/java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java')
-rw-r--r--services/java/com/android/server/SystemServer.java67
1 files changed, 66 insertions, 1 deletions
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 92f7bb7195b1..d95f17f401f1 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -23,6 +23,8 @@ import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
import static android.os.IServiceManager.DUMP_FLAG_PROTO;
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.myPid;
+import static android.system.OsConstants.O_CLOEXEC;
+import static android.system.OsConstants.O_RDONLY;
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.server.utils.TimingsTraceAndSlog.SYSTEM_SERVER_TIMING_TAG;
@@ -75,6 +77,8 @@ import android.provider.DeviceConfig;
import android.provider.Settings;
import android.server.ServerProtoEnums;
import android.sysprop.VoldProperties;
+import android.system.ErrnoException;
+import android.system.Os;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -189,6 +193,7 @@ import dalvik.system.VMRuntime;
import com.google.android.startop.iorap.IorapForwardingService;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Locale;
@@ -397,11 +402,71 @@ public final class SystemServer {
*/
private static native void initZygoteChildHeapProfiling();
+ private static final String SYSPROP_FDTRACK_ENABLE_THRESHOLD =
+ "persist.sys.debug.fdtrack_enable_threshold";
+ private static final String SYSPROP_FDTRACK_ABORT_THRESHOLD =
+ "persist.sys.debug.fdtrack_abort_threshold";
+ private static final String SYSPROP_FDTRACK_INTERVAL =
+ "persist.sys.debug.fdtrack_interval";
+
+ private static int getMaxFd() {
+ FileDescriptor fd = null;
+ try {
+ fd = Os.open("/dev/null", O_RDONLY | O_CLOEXEC, 0);
+ return fd.getInt$();
+ } catch (ErrnoException ex) {
+ Slog.e("System", "Failed to get maximum fd: " + ex);
+ } finally {
+ if (fd != null) {
+ try {
+ Os.close(fd);
+ } catch (ErrnoException ex) {
+ // If Os.close threw, something went horribly wrong.
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+
+ return Integer.MAX_VALUE;
+ }
+
+ private static native void fdtrackAbort();
/**
* Spawn a thread that monitors for fd leaks.
*/
- private static native void spawnFdLeakCheckThread();
+ private static void spawnFdLeakCheckThread() {
+ final int enableThreshold = SystemProperties.getInt(SYSPROP_FDTRACK_ENABLE_THRESHOLD, 1024);
+ final int abortThreshold = SystemProperties.getInt(SYSPROP_FDTRACK_ABORT_THRESHOLD, 2048);
+ final int checkInterval = SystemProperties.getInt(SYSPROP_FDTRACK_INTERVAL, 120);
+
+ new Thread(() -> {
+ boolean enabled = false;
+ while (true) {
+ int maxFd = getMaxFd();
+ if (maxFd > enableThreshold) {
+ // Do a manual GC to clean up fds that are hanging around as garbage.
+ System.gc();
+ maxFd = getMaxFd();
+ }
+
+ if (maxFd > enableThreshold && !enabled) {
+ Slog.i("System", "fdtrack enable threshold reached, enabling");
+ System.loadLibrary("fdtrack");
+ enabled = true;
+ } else if (maxFd > abortThreshold) {
+ Slog.i("System", "fdtrack abort threshold reached, dumping and aborting");
+ fdtrackAbort();
+ }
+
+ try {
+ Thread.sleep(checkInterval);
+ } catch (InterruptedException ex) {
+ continue;
+ }
+ }
+ }).start();
+ }
/**
* Start native Incremental Service and get its handle.