We're going to use HangDetails as the type containing hang information. We'll have a JS component which reads the data out of nsIHangDetails, builds the payload, and submits it to telemetry for us. We'll do it in JS because telemetry has to be submitted from JS. This patch also adds IPC serization for the relevant types so that we can send HangDetails objects over IPDL. MozReview-Commit-ID: CeikKabY9Vs
135 lines
4.3 KiB
C++
135 lines
4.3 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* 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 mozilla_ThreadStackHelper_h
|
|
#define mozilla_ThreadStackHelper_h
|
|
|
|
#include "js/ProfilingStack.h"
|
|
#include "HangDetails.h"
|
|
|
|
#include <stddef.h>
|
|
|
|
#if defined(XP_LINUX)
|
|
#include <signal.h>
|
|
#include <semaphore.h>
|
|
#include <sys/types.h>
|
|
#elif defined(XP_WIN)
|
|
#include <windows.h>
|
|
#elif defined(XP_MACOSX)
|
|
#include <mach/mach.h>
|
|
#endif
|
|
|
|
// Support pseudostack and native stack on these platforms.
|
|
#if defined(XP_LINUX) || defined(XP_WIN) || defined(XP_MACOSX)
|
|
# ifdef MOZ_GECKO_PROFILER
|
|
# define MOZ_THREADSTACKHELPER_PSEUDO
|
|
# define MOZ_THREADSTACKHELPER_NATIVE
|
|
# endif
|
|
#endif
|
|
|
|
|
|
// Android x86 builds consistently crash in the Background Hang Reporter. bug
|
|
// 1368520.
|
|
#if defined(__ANDROID__)
|
|
# undef MOZ_THREADSTACKHELPER_PSEUDO
|
|
# undef MOZ_THREADSTACKHELPER_NATIVE
|
|
#endif
|
|
|
|
namespace mozilla {
|
|
|
|
/**
|
|
* ThreadStackHelper is used to retrieve the profiler pseudo-stack of a
|
|
* thread, as an alternative of using the profiler to take a profile.
|
|
* The target thread first declares an ThreadStackHelper instance;
|
|
* then another thread can call ThreadStackHelper::GetStack to retrieve
|
|
* the pseudo-stack of the target thread at that instant.
|
|
*
|
|
* Only non-copying labels are included in the stack, which means labels
|
|
* with custom text and markers are not included.
|
|
*/
|
|
class ThreadStackHelper
|
|
{
|
|
public:
|
|
typedef HangStack Stack;
|
|
|
|
// When a native stack is gathered, this vector holds the raw program counter
|
|
// values that FramePointerStackWalk will return to us after it walks the
|
|
// stack. When gathering the Telemetry payload, Telemetry will take care of
|
|
// mapping these program counters to proper addresses within modules.
|
|
typedef NativeHangStack NativeStack;
|
|
|
|
private:
|
|
#ifdef MOZ_THREADSTACKHELPER_PSEUDO
|
|
Stack* mStackToFill;
|
|
const PseudoStack* const mPseudoStack;
|
|
size_t mMaxStackSize;
|
|
size_t mMaxBufferSize;
|
|
#endif
|
|
#ifdef MOZ_THREADSTACKHELPER_NATIVE
|
|
NativeStack* mNativeStackToFill;
|
|
#endif
|
|
|
|
bool PrepareStackBuffer(Stack& aStack);
|
|
void FillStackBuffer();
|
|
#ifdef MOZ_THREADSTACKHELPER_PSEUDO
|
|
const char* AppendJSEntry(const js::ProfileEntry* aEntry,
|
|
intptr_t& aAvailableBufferSize,
|
|
const char* aPrevLabel);
|
|
#endif
|
|
|
|
public:
|
|
/**
|
|
* Create a ThreadStackHelper instance targeting the current thread.
|
|
*/
|
|
ThreadStackHelper();
|
|
|
|
/**
|
|
* Retrieve the current pseudostack of the thread associated
|
|
* with this ThreadStackHelper.
|
|
*
|
|
* @param aStack Stack instance to be filled.
|
|
* @param aRunnableName The name of the current runnable on the target thread.
|
|
*/
|
|
void GetPseudoStack(Stack& aStack, nsACString& aRunnableName);
|
|
|
|
/**
|
|
* Retrieve the current native stack of the thread associated
|
|
* with this ThreadStackHelper.
|
|
*
|
|
* @param aNativeStack NativeStack instance to be filled.
|
|
* @param aRunnableName The name of the current runnable on the target thread.
|
|
*/
|
|
void GetNativeStack(NativeStack& aNativeStack, nsACString& aRunnableName);
|
|
|
|
/**
|
|
* Retrieve the current pseudostack and native stack of the thread associated
|
|
* with this ThreadStackHelper. This method only pauses the target thread once
|
|
* to get both stacks.
|
|
*
|
|
* @param aStack Stack instance to be filled with the pseudostack.
|
|
* @param aNativeStack NativeStack instance to be filled with the native stack.
|
|
* @param aRunnableName The name of the current runnable on the target thread.
|
|
*/
|
|
void GetPseudoAndNativeStack(Stack& aStack,
|
|
NativeStack& aNativeStack,
|
|
nsACString& aRunnableName);
|
|
|
|
private:
|
|
// Fill in the passed aStack and aNativeStack datastructures with backtraces.
|
|
// If only aStack needs to be collected, nullptr may be passed for
|
|
// aNativeStack, and vice versa.
|
|
void GetStacksInternal(Stack* aStack,
|
|
NativeStack* aNativeStack,
|
|
nsACString& aRunnableName);
|
|
|
|
// The profiler's unique thread identifier for the target thread.
|
|
int mThreadId;
|
|
};
|
|
|
|
} // namespace mozilla
|
|
|
|
#endif // mozilla_ThreadStackHelper_h
|