Android: Add option to print native stack traces in PeerConnectionFactory API
This CL hooks up the recently added native stack trace functionality to
the existing PeerConnectionFactory API.
Bug: webrtc:10168
Change-Id: I16189d2988b1359fc53f9a4d0b3d06f34e2a8fd5
Reviewed-on: https://webrtc-review.googlesource.com/c/118600
Reviewed-by: Tommi <tommi@webrtc.org>
Commit-Queue: Magnus Jedvert <magjed@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26344}
diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn
index 534865e..c6ffe73 100644
--- a/sdk/android/BUILD.gn
+++ b/sdk/android/BUILD.gn
@@ -784,6 +784,7 @@
":generated_peerconnection_jni",
":logging_jni",
":native_api_jni",
+ ":native_api_stacktrace",
"../..:webrtc_common",
"../../api:libjingle_peerconnection_api",
"../../api/video_codecs:video_codecs_api",
diff --git a/sdk/android/api/org/webrtc/PeerConnectionFactory.java b/sdk/android/api/org/webrtc/PeerConnectionFactory.java
index b68c816..6d00baa 100644
--- a/sdk/android/api/org/webrtc/PeerConnectionFactory.java
+++ b/sdk/android/api/org/webrtc/PeerConnectionFactory.java
@@ -11,6 +11,7 @@
package org.webrtc;
import android.content.Context;
+import android.os.Process;
import android.support.annotation.Nullable;
import java.util.List;
import org.webrtc.Logging.Severity;
@@ -29,17 +30,32 @@
private static final String TAG = "PeerConnectionFactory";
private static final String VIDEO_CAPTURER_THREAD_NAME = "VideoCapturerThread";
+ /** Helper class holding both Java and C++ thread info. */
+ private static class ThreadInfo {
+ final Thread thread;
+ final int tid;
+
+ public static ThreadInfo getCurrent() {
+ return new ThreadInfo(Thread.currentThread(), Process.myTid());
+ }
+
+ private ThreadInfo(Thread thread, int tid) {
+ this.thread = thread;
+ this.tid = tid;
+ }
+ }
+
private static volatile boolean internalTracerInitialized;
// Remove these once deprecated static printStackTrace() is gone.
- @Nullable private static Thread staticNetworkThread;
- @Nullable private static Thread staticWorkerThread;
- @Nullable private static Thread staticSignalingThread;
+ @Nullable private static ThreadInfo staticNetworkThread;
+ @Nullable private static ThreadInfo staticWorkerThread;
+ @Nullable private static ThreadInfo staticSignalingThread;
private long nativeFactory;
- @Nullable private volatile Thread networkThread;
- @Nullable private volatile Thread workerThread;
- @Nullable private volatile Thread signalingThread;
+ @Nullable private volatile ThreadInfo networkThread;
+ @Nullable private volatile ThreadInfo workerThread;
+ @Nullable private volatile ThreadInfo signalingThread;
public static class InitializationOptions {
final Context applicationContext;
@@ -471,24 +487,37 @@
}
}
- private static void printStackTrace(@Nullable Thread thread, String threadName) {
- if (thread != null) {
- StackTraceElement[] stackTraces = thread.getStackTrace();
- if (stackTraces.length > 0) {
- Logging.w(TAG, threadName + " stacks trace:");
- for (StackTraceElement stackTrace : stackTraces) {
- Logging.w(TAG, stackTrace.toString());
- }
+ private static void printStackTrace(
+ @Nullable ThreadInfo threadInfo, boolean printNativeStackTrace) {
+ if (threadInfo == null) {
+ // Thread callbacks have not been completed yet, ignore call.
+ return;
+ }
+ final String threadName = threadInfo.thread.getName();
+ StackTraceElement[] stackTraces = threadInfo.thread.getStackTrace();
+ if (stackTraces.length > 0) {
+ Logging.w(TAG, threadName + " stacktrace:");
+ for (StackTraceElement stackTrace : stackTraces) {
+ Logging.w(TAG, stackTrace.toString());
}
}
+ if (printNativeStackTrace) {
+ // Imitate output from debuggerd/tombstone so that stack trace can easily be symbolized with
+ // ndk-stack.
+ Logging.w(TAG, "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***");
+ Logging.w(TAG,
+ "pid: " + Process.myPid() + ", tid: " + threadInfo.tid + ", name: " + threadName
+ + " >>> WebRTC <<<");
+ nativePrintStackTrace(threadInfo.tid);
+ }
}
/** Deprecated, use non-static version instead. */
@Deprecated
public static void printStackTraces() {
- printStackTrace(staticNetworkThread, "Network thread");
- printStackTrace(staticWorkerThread, "Worker thread");
- printStackTrace(staticSignalingThread, "Signaling thread");
+ printStackTrace(staticNetworkThread, /* printNativeStackTrace= */ false);
+ printStackTrace(staticWorkerThread, /* printNativeStackTrace= */ false);
+ printStackTrace(staticSignalingThread, /* printNativeStackTrace= */ false);
}
/**
@@ -497,28 +526,28 @@
* attempt to print the C++ stack traces for these threads.
*/
public void printInternalStackTraces(boolean printNativeStackTraces) {
- printStackTrace(signalingThread, "Signaling thread");
- printStackTrace(workerThread, "Worker thread");
- printStackTrace(networkThread, "Network thread");
+ printStackTrace(signalingThread, printNativeStackTraces);
+ printStackTrace(workerThread, printNativeStackTraces);
+ printStackTrace(networkThread, printNativeStackTraces);
}
@CalledByNative
private void onNetworkThreadReady() {
- networkThread = Thread.currentThread();
+ networkThread = ThreadInfo.getCurrent();
staticNetworkThread = networkThread;
Logging.d(TAG, "onNetworkThreadReady");
}
@CalledByNative
private void onWorkerThreadReady() {
- workerThread = Thread.currentThread();
+ workerThread = ThreadInfo.getCurrent();
staticWorkerThread = workerThread;
Logging.d(TAG, "onWorkerThreadReady");
}
@CalledByNative
private void onSignalingThreadReady() {
- signalingThread = Thread.currentThread();
+ signalingThread = ThreadInfo.getCurrent();
staticSignalingThread = signalingThread;
Logging.d(TAG, "onSignalingThreadReady");
}
@@ -558,4 +587,5 @@
private static native long nativeGetNativePeerConnectionFactory(long factory);
private static native void nativeInjectLoggable(JNILogging jniLogging, int severity);
private static native void nativeDeleteLoggable();
+ private static native void nativePrintStackTrace(int tid);
}
diff --git a/sdk/android/src/jni/pc/peer_connection_factory.cc b/sdk/android/src/jni/pc/peer_connection_factory.cc
index 040753d..79ac732 100644
--- a/sdk/android/src/jni/pc/peer_connection_factory.cc
+++ b/sdk/android/src/jni/pc/peer_connection_factory.cc
@@ -26,6 +26,7 @@
#include "rtc_base/thread.h"
#include "sdk/android/generated_peerconnection_jni/jni/PeerConnectionFactory_jni.h"
#include "sdk/android/native_api/jni/java_types.h"
+#include "sdk/android/native_api/stacktrace/stacktrace.h"
#include "sdk/android/src/jni/jni_helpers.h"
#include "sdk/android/src/jni/logging/log_sink.h"
#include "sdk/android/src/jni/pc/android_network_monitor.h"
@@ -515,5 +516,9 @@
}
}
+static void JNI_PeerConnectionFactory_PrintStackTrace(JNIEnv* env, jint tid) {
+ RTC_LOG(LS_WARNING) << StackTraceToString(GetStackTrace(tid));
+}
+
} // namespace jni
} // namespace webrtc