Skip to content

Commit

Permalink
Bug 1182641 - Implement new native methods for ANRReporter; r=snorp
Browse files Browse the repository at this point in the history
  • Loading branch information
Jim Chen committed Jul 29, 2015
1 parent 0ecddc5 commit c8a60c5
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 76 deletions.
89 changes: 89 additions & 0 deletions widget/android/ANRReporter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "ANRReporter.h"
#include "GeckoProfiler.h"

#include <unistd.h>

namespace mozilla {

bool
ANRReporter::RequestNativeStack(bool aUnwind)
{
if (profiler_is_active()) {
// Don't proceed if profiler is already running
return false;
}
// WARNING: we are on the ANR reporter thread at this point and it is
// generally unsafe to use the profiler from off the main thread. However,
// the risk here is limited because for most users, the profiler is not run
// elsewhere. See the discussion in Bug 863777, comment 13
const char *NATIVE_STACK_FEATURES[] =
{"leaf", "threads", "privacy"};
const char *NATIVE_STACK_UNWIND_FEATURES[] =
{"leaf", "threads", "privacy", "stackwalk"};

const char **features = NATIVE_STACK_FEATURES;
size_t features_size = sizeof(NATIVE_STACK_FEATURES);
if (aUnwind) {
features = NATIVE_STACK_UNWIND_FEATURES;
features_size = sizeof(NATIVE_STACK_UNWIND_FEATURES);
// We want the new unwinder if the unwind mode has not been set yet
putenv("MOZ_PROFILER_NEW=1");
}

const char *NATIVE_STACK_THREADS[] =
{"GeckoMain", "Compositor"};
// Buffer one sample and let the profiler wait a long time
profiler_start(100, 10000, features, features_size / sizeof(char*),
NATIVE_STACK_THREADS, sizeof(NATIVE_STACK_THREADS) / sizeof(char*));
return true;
}

jni::String::LocalRef
ANRReporter::GetNativeStack()
{
if (!profiler_is_active()) {
// Maybe profiler support is disabled?
return nullptr;
}

// Timeout if we don't get a profiler sample after 5 seconds.
const PRIntervalTime timeout = PR_SecondsToInterval(5);
const PRIntervalTime startTime = PR_IntervalNow();

// Pointer to a profile JSON string
typedef mozilla::UniquePtr<char[]> ProfilePtr;

ProfilePtr profile(profiler_get_profile());

while (profile && !strstr(profile.get(), "\"samples\":[{")) {
// no sample yet?
if (PR_IntervalNow() - startTime >= timeout) {
return nullptr;
}
usleep(100000ul); // Sleep for 100ms
profile = ProfilePtr(profiler_get_profile());
}

if (profile) {
return jni::String::Param(profile.get());
}
return nullptr;
}

void
ANRReporter::ReleaseNativeStack()
{
if (!profiler_is_active()) {
// Maybe profiler support is disabled?
return;
}
mozilla_sampler_stop();
}

} // namespace

26 changes: 26 additions & 0 deletions widget/android/ANRReporter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef ANRReporter_h__
#define ANRReporter_h__

#include "GeneratedJNINatives.h"

namespace mozilla {

class ANRReporter : public widget::ANRReporter::Natives<ANRReporter>
{
private:
ANRReporter();

public:
static bool RequestNativeStack(bool aUnwind);
static jni::String::LocalRef GetNativeStack();
static void ReleaseNativeStack();
};

} // namespace

#endif // ANRReporter_h__
3 changes: 3 additions & 0 deletions widget/android/AndroidBridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
#include "SurfaceTexture.h"
#include "GLContextProvider.h"

#include "ANRReporter.h"

using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::jni;
Expand Down Expand Up @@ -249,6 +251,7 @@ AndroidBridge::Init(JNIEnv *jEnv, Object::Param clsLoader)
jAvailable = inputStream.getMethod("available", "()I");

InitAndroidJavaWrappers(jEnv);
ANRReporter::Init();

// jEnv should NOT be cached here by anything -- the jEnv here
// is not valid for the real gecko main thread, which is set
Expand Down
76 changes: 0 additions & 76 deletions widget/android/AndroidJNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
#include "nsIMobileMessageDatabaseService.h"
#include "nsPluginInstanceOwner.h"
#include "AndroidSurfaceTexture.h"
#include "GeckoProfiler.h"
#include "nsMemoryPressure.h"

using namespace mozilla;
Expand Down Expand Up @@ -970,79 +969,4 @@ Java_org_mozilla_gecko_gfx_NativePanZoomController_getOverScrollMode(JNIEnv* env
return 0;
}

NS_EXPORT jboolean JNICALL
Java_org_mozilla_gecko_ANRReporter_requestNativeStack(JNIEnv*, jclass, jboolean aUnwind)
{
if (profiler_is_active()) {
// Don't proceed if profiler is already running
return JNI_FALSE;
}
// WARNING: we are on the ANR reporter thread at this point and it is
// generally unsafe to use the profiler from off the main thread. However,
// the risk here is limited because for most users, the profiler is not run
// elsewhere. See the discussion in Bug 863777, comment 13
const char *NATIVE_STACK_FEATURES[] =
{"leaf", "threads", "privacy"};
const char *NATIVE_STACK_UNWIND_FEATURES[] =
{"leaf", "threads", "privacy", "stackwalk"};

const char **features = NATIVE_STACK_FEATURES;
size_t features_size = sizeof(NATIVE_STACK_FEATURES);
if (aUnwind) {
features = NATIVE_STACK_UNWIND_FEATURES;
features_size = sizeof(NATIVE_STACK_UNWIND_FEATURES);
// We want the new unwinder if the unwind mode has not been set yet
putenv("MOZ_PROFILER_NEW=1");
}

const char *NATIVE_STACK_THREADS[] =
{"GeckoMain", "Compositor"};
// Buffer one sample and let the profiler wait a long time
profiler_start(100, 10000, features, features_size / sizeof(char*),
NATIVE_STACK_THREADS, sizeof(NATIVE_STACK_THREADS) / sizeof(char*));
return JNI_TRUE;
}

NS_EXPORT jstring JNICALL
Java_org_mozilla_gecko_ANRReporter_getNativeStack(JNIEnv* jenv, jclass)
{
if (!profiler_is_active()) {
// Maybe profiler support is disabled?
return nullptr;
}

// Timeout if we don't get a profiler sample after 5 seconds.
const PRIntervalTime timeout = PR_SecondsToInterval(5);
const PRIntervalTime startTime = PR_IntervalNow();

// Pointer to a profile JSON string
typedef mozilla::UniquePtr<char[]> ProfilePtr;

ProfilePtr profile(profiler_get_profile());

while (profile && !strstr(profile.get(), "\"samples\":[{")) {
// no sample yet?
if (PR_IntervalNow() - startTime >= timeout) {
return nullptr;
}
usleep(100000ul); // Sleep for 100ms
profile = ProfilePtr(profiler_get_profile());
}

if (profile) {
return jenv->NewStringUTF(profile.get());
}
return nullptr;
}

NS_EXPORT void JNICALL
Java_org_mozilla_gecko_ANRReporter_releaseNativeStack(JNIEnv* jenv, jclass)
{
if (!profiler_is_active()) {
// Maybe profiler support is disabled?
return;
}
mozilla_sampler_stop();
}

}
1 change: 1 addition & 0 deletions widget/android/moz.build
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ SOURCES += [
'AndroidJavaWrappers.cpp',
'AndroidJNI.cpp',
'AndroidJNIWrapper.cpp',
'ANRReporter.cpp',
'GeneratedJNIWrappers.cpp',
'GfxInfo.cpp',
'NativeJSContainer.cpp',
Expand Down

0 comments on commit c8a60c5

Please sign in to comment.