DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (92ad4fa429a6)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
/* -*- Mode: c++; c-basic-offset: 2; 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) {
#ifdef MOZ_GECKO_PROFILER
  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
  uint32_t features = ProfilerFeature::Leaf | ProfilerFeature::Privacy |
                      (aUnwind ? ProfilerFeature::StackWalk : 0) |
                      ProfilerFeature::Threads;

  const char* NATIVE_STACK_THREADS[] = {"GeckoMain", "Compositor"};

  // Buffer one sample and let the profiler wait a long time
  profiler_start(/* entries */ PowerOfTwo<uint32_t>(100), /* interval */ 10000,
                 features, NATIVE_STACK_THREADS,
                 sizeof(NATIVE_STACK_THREADS) / sizeof(char*));
#endif
  return true;
}

jni::String::LocalRef ANRReporter::GetNativeStack() {
#ifdef MOZ_GECKO_PROFILER
  // 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;

  // profiler_get_profile() will return nullptr if the profiler is inactive.
  ProfilePtr profile(profiler_get_profile());
  if (!profile) {
    return nullptr;
  }

  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());
  }
#endif
  return nullptr;
}

void ANRReporter::ReleaseNativeStack() {
#ifdef MOZ_GECKO_PROFILER
  if (!profiler_is_active()) {
    // Maybe profiler support is disabled?
    return;
  }
  profiler_stop();
#endif
}

}  // namespace mozilla