Skip to content

Commit

Permalink
[feature] Add network info to the tombstone files.
Browse files Browse the repository at this point in the history
Network info comes from:
1. /proc/self/net/tcp
2. /proc/self/net/tcp6
3. /proc/self/net/udp
4. /proc/self/net/udp6
5. /proc/self/net/icmp
6. /proc/self/net/icmp6
7. /proc/self/net/unix

Notes: These network info is not supported on Android Q (API level 29) and later. (ref: https://developer.android.com/about/versions/10/privacy/changes#proc-net-filesystem)
  • Loading branch information
caikelun committed Nov 15, 2019
1 parent 89a99ac commit 04a642b
Show file tree
Hide file tree
Showing 21 changed files with 236 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class AnrHandler {
private int logcatEventsLines;
private int logcatMainLines;
private boolean dumpFds;
private boolean dumpNetworkInfo;
private ICrashCallback callback;
private long lastTime = 0;
private FileObserver fileObserver = null;
Expand All @@ -74,7 +75,7 @@ static AnrHandler getInstance() {
@SuppressWarnings("deprecation")
void initialize(Context ctx, int pid, String processName, String appId, String appVersion, String logDir,
boolean checkProcessState, int logcatSystemLines, int logcatEventsLines, int logcatMainLines,
boolean dumpFds, ICrashCallback callback) {
boolean dumpFds, boolean dumpNetworkInfo, ICrashCallback callback) {

//check API level
if (Build.VERSION.SDK_INT >= 21) {
Expand All @@ -92,6 +93,7 @@ void initialize(Context ctx, int pid, String processName, String appId, String a
this.logcatEventsLines = logcatEventsLines;
this.logcatMainLines = logcatMainLines;
this.dumpFds = dumpFds;
this.dumpNetworkInfo = dumpNetworkInfo;
this.callback = callback;

fileObserver = new FileObserver("/data/anr/", CLOSE_WRITE) {
Expand Down Expand Up @@ -199,6 +201,11 @@ private void handleAnr(String filepath) {
raf.write(Util.getFds().getBytes("UTF-8"));
}

//write network info
if (dumpNetworkInfo) {
raf.write(Util.getNetworkInfo().getBytes("UTF-8"));
}

//write memory info
raf.write(Util.getMemoryInfo().getBytes("UTF-8"));
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class JavaCrashHandler implements UncaughtExceptionHandler {
private int logcatEventsLines;
private int logcatMainLines;
private boolean dumpFds;
private boolean dumpNetworkInfo;
private boolean dumpAllThreads;
private int dumpAllThreadsCountMax;
private String[] dumpAllThreadsWhiteList;
Expand All @@ -69,7 +70,7 @@ static JavaCrashHandler getInstance() {

void initialize(int pid, String processName, String appId, String appVersion, String logDir, boolean rethrow,
int logcatSystemLines, int logcatEventsLines, int logcatMainLines,
boolean dumpFds, boolean dumpAllThreads, int dumpAllThreadsCountMax, String[] dumpAllThreadsWhiteList,
boolean dumpFds, boolean dumpNetworkInfo, boolean dumpAllThreads, int dumpAllThreadsCountMax, String[] dumpAllThreadsWhiteList,
ICrashCallback callback) {
this.pid = pid;
this.processName = (TextUtils.isEmpty(processName) ? "unknown" : processName);
Expand All @@ -81,6 +82,7 @@ void initialize(int pid, String processName, String appId, String appVersion, St
this.logcatEventsLines = logcatEventsLines;
this.logcatMainLines = logcatMainLines;
this.dumpFds = dumpFds;
this.dumpNetworkInfo = dumpNetworkInfo;
this.dumpAllThreads = dumpAllThreads;
this.dumpAllThreadsCountMax = dumpAllThreadsCountMax;
this.dumpAllThreadsWhiteList = dumpAllThreadsWhiteList;
Expand Down Expand Up @@ -165,6 +167,11 @@ private void handleException(Thread thread, Throwable throwable) {
raf.write(Util.getFds().getBytes("UTF-8"));
}

//write network info
if (dumpNetworkInfo) {
raf.write(Util.getNetworkInfo().getBytes("UTF-8"));
}

//write memory info
raf.write(Util.getMemoryInfo().getBytes("UTF-8"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ int initialize(Context ctx,
boolean crashDumpElfHash,
boolean crashDumpMap,
boolean crashDumpFds,
boolean crashDumpNetworkInfo,
boolean crashDumpAllThreads,
int crashDumpAllThreadsCountMax,
String[] crashDumpAllThreadsWhiteList,
Expand All @@ -76,6 +77,7 @@ int initialize(Context ctx,
int anrLogcatEventsLines,
int anrLogcatMainLines,
boolean anrDumpFds,
boolean anrDumpNetworkInfo,
ICrashCallback anrCallback) {
//load lib
if (libLoader == null) {
Expand Down Expand Up @@ -124,6 +126,7 @@ int initialize(Context ctx,
crashDumpElfHash,
crashDumpMap,
crashDumpFds,
crashDumpNetworkInfo,
crashDumpAllThreads,
crashDumpAllThreadsCountMax,
crashDumpAllThreadsWhiteList,
Expand All @@ -132,7 +135,8 @@ int initialize(Context ctx,
anrLogcatSystemLines,
anrLogcatEventsLines,
anrLogcatMainLines,
anrDumpFds);
anrDumpFds,
anrDumpNetworkInfo);
if (r != 0) {
XCrash.getLogger().e(Util.TAG, "NativeHandler init failed");
return Errno.INIT_LIBRARY_FAILED;
Expand Down Expand Up @@ -275,6 +279,7 @@ private static native int nativeInit(
boolean crashDumpElfHash,
boolean crashDumpMap,
boolean crashDumpFds,
boolean crashDumpNetworkInfo,
boolean crashDumpAllThreads,
int crashDumpAllThreadsCountMax,
String[] crashDumpAllThreadsWhiteList,
Expand All @@ -283,7 +288,8 @@ private static native int nativeInit(
int traceLogcatSystemLines,
int traceLogcatEventsLines,
int traceLogcatMainLines,
boolean traceDumpFds);
boolean traceDumpFds,
boolean traceDumpNetworkInfo);

private static native void nativeNotifyJavaCrashed();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,12 @@ public class TombstoneParser {
@SuppressWarnings("WeakerAccess")
public static final String keyOpenFiles = "open files";

/**
* Network info.
*/
@SuppressWarnings("WeakerAccess")
public static final String keyNetworkInfo = "network info";

/**
* Memory info. (From: /proc/PID/smaps)
*/
Expand Down
52 changes: 46 additions & 6 deletions src/java/xcrash/xcrash_lib/src/main/java/xcrash/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -204,17 +204,28 @@ static String getProcessMemoryInfo() {
}

private static String getFileContent(String pathname) {
return getFileContent(pathname, 0);
}

private static String getFileContent(String pathname, int limit) {
StringBuilder sb = new StringBuilder();
BufferedReader br = null;
String line;
int n = 0;
try {
br = new BufferedReader(new FileReader(pathname));
while (null != (line = br.readLine())) {
String p = line.trim();
if (p.length() > 0) {
sb.append(" ").append(p).append("\n");
n++;
if (limit == 0 || n <= limit) {
sb.append(" ").append(p).append("\n");
}
}
}
if (limit > 0 && n > limit) {
sb.append(" ......\n").append(" (number of records: ").append(n).append(")\n");
}
} catch (Exception e) {
XCrash.getLogger().i(Util.TAG, "Util getInfo(" + pathname + ") failed", e);
} finally {
Expand Down Expand Up @@ -290,27 +301,56 @@ static String getLogHeader(Date startTime, Date crashTime, String crashType, Str
}

static String getMemoryInfo() {
int pid = android.os.Process.myPid();
return "memory info:\n"
+ " System Summary (From: /proc/meminfo)\n"
+ Util.getFileContent("/proc/meminfo")
+ "-\n"
+ " Process Status (From: /proc/PID/status)\n"
+ Util.getFileContent("/proc/" + pid + "/status")
+ Util.getFileContent("/proc/self/status")
+ "-\n"
+ " Process Limits (From: /proc/PID/limits)\n"
+ Util.getFileContent("/proc/" + pid + "/limits")
+ Util.getFileContent("/proc/self/limits")
+ "-\n"
+ Util.getProcessMemoryInfo()
+ "\n";
}

static String getNetworkInfo() {
if (Build.VERSION.SDK_INT >= 29) {
return "network info:\n"
+ "Not supported on Android Q (API level 29) and later.\n"
+ "\n";
} else {
return "network info:\n"
+ " TCP over IPv4 (From: /proc/PID/net/tcp)\n"
+ Util.getFileContent("/proc/self/net/tcp", 1024)
+ "-\n"
+ " TCP over IPv6 (From: /proc/PID/net/tcp6)\n"
+ Util.getFileContent("/proc/self/net/tcp6", 1024)
+ "-\n"
+ " UDP over IPv4 (From: /proc/PID/net/udp)\n"
+ Util.getFileContent("/proc/self/net/udp", 1024)
+ "-\n"
+ " UDP over IPv6 (From: /proc/PID/net/udp6)\n"
+ Util.getFileContent("/proc/self/net/udp6", 1024)
+ "-\n"
+ " ICMP in IPv4 (From: /proc/PID/net/icmp)\n"
+ Util.getFileContent("/proc/self/net/icmp", 256)
+ "-\n"
+ " ICMP in IPv6 (From: /proc/PID/net/icmp6)\n"
+ Util.getFileContent("/proc/self/net/icmp6", 256)
+ "-\n"
+ " UNIX domain (From: /proc/PID/net/unix)\n"
+ Util.getFileContent("/proc/self/net/unix", 256)
+ "\n";
}
}

static String getFds() {
int pid = android.os.Process.myPid();
StringBuilder sb = new StringBuilder("open files:\n");

try {
File dir = new File("/proc/" + pid + "/fd");
File dir = new File("/proc/self/fd");
File[] fds = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
Expand Down
43 changes: 43 additions & 0 deletions src/java/xcrash/xcrash_lib/src/main/java/xcrash/XCrash.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ public static synchronized int init(Context ctx, InitParameters params) {
params.javaLogcatEventsLines,
params.javaLogcatMainLines,
params.javaDumpFds,
params.javaDumpNetworkInfo,
params.javaDumpAllThreads,
params.javaDumpAllThreadsCountMax,
params.javaDumpAllThreadsWhiteList,
Expand All @@ -173,6 +174,7 @@ public static synchronized int init(Context ctx, InitParameters params) {
params.anrLogcatEventsLines,
params.anrLogcatMainLines,
params.anrDumpFds,
params.anrDumpNetworkInfo,
params.anrCallback);
}

Expand All @@ -193,6 +195,7 @@ public static synchronized int init(Context ctx, InitParameters params) {
params.nativeDumpElfHash,
params.nativeDumpMap,
params.nativeDumpFds,
params.nativeDumpNetworkInfo,
params.nativeDumpAllThreads,
params.nativeDumpAllThreadsCountMax,
params.nativeDumpAllThreadsWhiteList,
Expand All @@ -204,6 +207,7 @@ public static synchronized int init(Context ctx, InitParameters params) {
params.anrLogcatEventsLines,
params.anrLogcatMainLines,
params.anrDumpFds,
params.anrDumpNetworkInfo,
params.anrCallback);
}

Expand Down Expand Up @@ -323,6 +327,7 @@ public InitParameters setPlaceholderSizeKb(int sizeKb) {
int javaLogcatEventsLines = 50;
int javaLogcatMainLines = 200;
boolean javaDumpFds = true;
boolean javaDumpNetworkInfo = true;
boolean javaDumpAllThreads = true;
int javaDumpAllThreadsCountMax = 0;
String[] javaDumpAllThreadsWhiteList = null;
Expand Down Expand Up @@ -423,6 +428,18 @@ public InitParameters setJavaDumpFds(boolean flag) {
return this;
}

/**
* Set if dumping network info when a java crash occurred. (Default: enable)
*
* @param flag True or false.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setJavaDumpNetworkInfo(boolean flag) {
this.javaDumpNetworkInfo = flag;
return this;
}

/**
* Set if dumping threads info (stacktrace) for all threads (not just the thread that has crashed)
* when a Java exception occurred. (Default: enable)
Expand Down Expand Up @@ -488,6 +505,7 @@ public InitParameters setJavaCallback(ICrashCallback callback) {
boolean nativeDumpElfHash = true;
boolean nativeDumpMap = true;
boolean nativeDumpFds = true;
boolean nativeDumpNetworkInfo = true;
boolean nativeDumpAllThreads = true;
int nativeDumpAllThreadsCountMax = 0;
String[] nativeDumpAllThreadsWhiteList = null;
Expand Down Expand Up @@ -612,6 +630,18 @@ public InitParameters setNativeDumpFds(boolean flag) {
return this;
}

/**
* Set if dumping network info when a native crash occurred. (Default: enable)
*
* @param flag True or false.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setNativeDumpNetwork(boolean flag) {
this.nativeDumpNetworkInfo = flag;
return this;
}

/**
* Set if dumping threads info (registers, backtrace and stack) for all threads (not just the thread that has crashed)
* when a native crash occurred. (Default: enable)
Expand Down Expand Up @@ -680,6 +710,7 @@ public InitParameters setNativeCallback(ICrashCallback callback) {
int anrLogcatEventsLines = 50;
int anrLogcatMainLines = 200;
boolean anrDumpFds = true;
boolean anrDumpNetworkInfo = true;
ICrashCallback anrCallback = null;

/**
Expand Down Expand Up @@ -795,6 +826,18 @@ public InitParameters setAnrDumpFds(boolean flag) {
return this;
}

/**
* Set if dumping network info when an ANR occurred. (Default: enable)
*
* @param flag True or false.
* @return The InitParameters object.
*/
@SuppressWarnings("unused")
public InitParameters setAnrDumpNetwork(boolean flag) {
this.anrDumpNetworkInfo = flag;
return this;
}

/**
* Set a callback to be executed when an ANR occurred. (If not set, nothing will be happened.)
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

import android.content.Intent;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;

Expand Down
Loading

0 comments on commit 04a642b

Please sign in to comment.