summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Elliott Hughes <enh@google.com> 2020-07-22 17:15:46 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2020-07-22 17:15:46 +0000
commit4a724fc1ee8344d45829d7069ae6a0b7c30c8d04 (patch)
tree5b6098768a151d9c5b623a44ed38ce4f52641190
parent6b54515b6165f36e90c5cef87484c8f5d32137e9 (diff)
parent6e75720db31f7312fd0443004563a2a9ccf4318c (diff)
Merge "Remove the watchdog's fd tracker."
-rw-r--r--services/core/java/com/android/server/Watchdog.java157
1 files changed, 22 insertions, 135 deletions
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 5f9d1d801441..25c8a3e6eafb 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -23,7 +23,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.hidl.manager.V1_0.IServiceManager;
import android.os.Binder;
-import android.os.Build;
import android.os.Debug;
import android.os.Handler;
import android.os.IPowerManager;
@@ -32,10 +31,6 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-import android.system.StructRlimit;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
@@ -48,13 +43,8 @@ import com.android.server.wm.SurfaceAnimationThread;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -132,7 +122,6 @@ public class Watchdog extends Thread {
int mPhonePid;
IActivityController mController;
boolean mAllowRestart = true;
- final OpenFdMonitor mOpenFdMonitor;
/**
* Used for checking status of handle threads and scheduling monitor callbacks.
@@ -337,8 +326,6 @@ public class Watchdog extends Thread {
// Initialize monitor for Binder threads.
addMonitor(new BinderThreadMonitor());
- mOpenFdMonitor = OpenFdMonitor.create();
-
// See the notes on DEFAULT_TIMEOUT.
assert DB ||
DEFAULT_TIMEOUT > ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS;
@@ -560,41 +547,31 @@ public class Watchdog extends Thread {
timeout = CHECK_INTERVAL - (SystemClock.uptimeMillis() - start);
}
- boolean fdLimitTriggered = false;
- if (mOpenFdMonitor != null) {
- fdLimitTriggered = mOpenFdMonitor.monitor();
- }
-
- if (!fdLimitTriggered) {
- final int waitState = evaluateCheckerCompletionLocked();
- if (waitState == COMPLETED) {
- // The monitors have returned; reset
- waitedHalf = false;
- continue;
- } else if (waitState == WAITING) {
- // still waiting but within their configured intervals; back off and recheck
- continue;
- } else if (waitState == WAITED_HALF) {
- if (!waitedHalf) {
- Slog.i(TAG, "WAITED_HALF");
- // We've waited half the deadlock-detection interval. Pull a stack
- // trace and wait another half.
- ArrayList<Integer> pids = new ArrayList<Integer>();
- pids.add(Process.myPid());
- ActivityManagerService.dumpStackTraces(pids, null, null,
+ final int waitState = evaluateCheckerCompletionLocked();
+ if (waitState == COMPLETED) {
+ // The monitors have returned; reset
+ waitedHalf = false;
+ continue;
+ } else if (waitState == WAITING) {
+ // still waiting but within their configured intervals; back off and recheck
+ continue;
+ } else if (waitState == WAITED_HALF) {
+ if (!waitedHalf) {
+ Slog.i(TAG, "WAITED_HALF");
+ // We've waited half the deadlock-detection interval. Pull a stack
+ // trace and wait another half.
+ ArrayList<Integer> pids = new ArrayList<Integer>();
+ pids.add(Process.myPid());
+ ActivityManagerService.dumpStackTraces(pids, null, null,
getInterestingNativePids());
- waitedHalf = true;
- }
- continue;
+ waitedHalf = true;
}
-
- // something is overdue!
- blockedCheckers = getBlockedCheckersLocked();
- subject = describeCheckersLocked(blockedCheckers);
- } else {
- blockedCheckers = Collections.emptyList();
- subject = "Open FD high water mark reached";
+ continue;
}
+
+ // something is overdue!
+ blockedCheckers = getBlockedCheckersLocked();
+ subject = describeCheckersLocked(blockedCheckers);
allowRestart = mAllowRestart;
}
@@ -688,94 +665,4 @@ public class Watchdog extends Thread {
Slog.w(TAG, "Failed to write to /proc/sysrq-trigger", e);
}
}
-
- public static final class OpenFdMonitor {
- /**
- * Number of FDs below the soft limit that we trigger a runtime restart at. This was
- * chosen arbitrarily, but will need to be at least 6 in order to have a sufficient number
- * of FDs in reserve to complete a dump.
- */
- private static final int FD_HIGH_WATER_MARK = 12;
-
- private final File mDumpDir;
- private final File mFdHighWaterMark;
-
- public static OpenFdMonitor create() {
- // Only run the FD monitor on debuggable builds (such as userdebug and eng builds).
- if (!Build.IS_DEBUGGABLE) {
- return null;
- }
-
- final StructRlimit rlimit;
- try {
- rlimit = android.system.Os.getrlimit(OsConstants.RLIMIT_NOFILE);
- } catch (ErrnoException errno) {
- Slog.w(TAG, "Error thrown from getrlimit(RLIMIT_NOFILE)", errno);
- return null;
- }
-
- // The assumption we're making here is that FD numbers are allocated (more or less)
- // sequentially, which is currently (and historically) true since open is currently
- // specified to always return the lowest-numbered non-open file descriptor for the
- // current process.
- //
- // We do this to avoid having to enumerate the contents of /proc/self/fd in order to
- // count the number of descriptors open in the process.
- final File fdThreshold = new File("/proc/self/fd/" + (rlimit.rlim_cur - FD_HIGH_WATER_MARK));
- return new OpenFdMonitor(new File("/data/anr"), fdThreshold);
- }
-
- OpenFdMonitor(File dumpDir, File fdThreshold) {
- mDumpDir = dumpDir;
- mFdHighWaterMark = fdThreshold;
- }
-
- /**
- * Dumps open file descriptors and their full paths to a temporary file in {@code mDumpDir}.
- */
- private void dumpOpenDescriptors() {
- // We cannot exec lsof to get more info about open file descriptors because a newly
- // forked process will not have the permissions to readlink. Instead list all open
- // descriptors from /proc/pid/fd and resolve them.
- List<String> dumpInfo = new ArrayList<>();
- String fdDirPath = String.format("/proc/%d/fd/", Process.myPid());
- File[] fds = new File(fdDirPath).listFiles();
- if (fds == null) {
- dumpInfo.add("Unable to list " + fdDirPath);
- } else {
- for (File f : fds) {
- String fdSymLink = f.getAbsolutePath();
- String resolvedPath = "";
- try {
- resolvedPath = Os.readlink(fdSymLink);
- } catch (ErrnoException ex) {
- resolvedPath = ex.getMessage();
- }
- dumpInfo.add(fdSymLink + "\t" + resolvedPath);
- }
- }
-
- // Dump the fds & paths to a temp file.
- try {
- File dumpFile = File.createTempFile("anr_fd_", "", mDumpDir);
- Path out = Paths.get(dumpFile.getAbsolutePath());
- Files.write(out, dumpInfo, StandardCharsets.UTF_8);
- } catch (IOException ex) {
- Slog.w(TAG, "Unable to write open descriptors to file: " + ex);
- }
- }
-
- /**
- * @return {@code true} if the high water mark was breached and a dump was written,
- * {@code false} otherwise.
- */
- public boolean monitor() {
- if (mFdHighWaterMark.exists()) {
- dumpOpenDescriptors();
- return true;
- }
-
- return false;
- }
- }
}