mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1213007 - Part 1. Implementing gfxCrash. r=dvander
This commit is contained in:
parent
8c01d793e6
commit
3450369434
@ -906,5 +906,13 @@ CriticalLogger::OutputMessage(const std::string &aString,
|
||||
BasicLogger::OutputMessage(aString, aLevel, aNoNewline);
|
||||
}
|
||||
|
||||
void
|
||||
CriticalLogger::CrashAction(LogReason aReason)
|
||||
{
|
||||
if (Factory::GetLogForwarder()) {
|
||||
Factory::GetLogForwarder()->CrashAction(aReason);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
@ -127,6 +127,17 @@ private:
|
||||
/// is further controlled by "gfx2d" PR logging module. However, in the case
|
||||
/// where such module would disable the output, in all but gfxDebug cases,
|
||||
/// we will still send a printf.
|
||||
|
||||
// The range is due to the values set in Histograms.json
|
||||
enum class LogReason : int {
|
||||
MustBeMoreThanThis = -1,
|
||||
// Start. Do not insert, always add at end. If you remove items,
|
||||
// make sure the other items retain their values.
|
||||
|
||||
// End
|
||||
MustBeLessThanThis = 101,
|
||||
};
|
||||
|
||||
struct BasicLogger
|
||||
{
|
||||
// For efficiency, this method exists and copies the logic of the
|
||||
@ -151,6 +162,9 @@ struct BasicLogger
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only for really critical errors.
|
||||
static void CrashAction(LogReason aReason) {}
|
||||
|
||||
static void OutputMessage(const std::string &aString,
|
||||
int aLevel,
|
||||
bool aNoNewline) {
|
||||
@ -183,6 +197,7 @@ struct BasicLogger
|
||||
|
||||
struct CriticalLogger {
|
||||
static void OutputMessage(const std::string &aString, int aLevel, bool aNoNewline);
|
||||
static void CrashAction(LogReason aReason);
|
||||
};
|
||||
|
||||
// Implement this interface and init the Factory with an instance to
|
||||
@ -191,6 +206,7 @@ class LogForwarder {
|
||||
public:
|
||||
virtual ~LogForwarder() {}
|
||||
virtual void Log(const std::string &aString) = 0;
|
||||
virtual void CrashAction(LogReason aReason) = 0;
|
||||
|
||||
// Provide a copy of the logs to the caller. The int is the index
|
||||
// of the Log call, if the number of logs exceeds some preset capacity
|
||||
@ -215,7 +231,8 @@ public:
|
||||
enum class LogOptions : int {
|
||||
NoNewline = 0x01,
|
||||
AutoPrefix = 0x02,
|
||||
AssertOnCall = 0x04
|
||||
AssertOnCall = 0x04,
|
||||
CrashAction = 0x08,
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@ -241,8 +258,9 @@ public:
|
||||
// Logger::ShouldOutputMessage. Since we currently don't have a different
|
||||
// version of that method for different loggers, this is OK. Once we do,
|
||||
// change BasicLogger::ShouldOutputMessage to Logger::ShouldOutputMessage.
|
||||
explicit Log(int aOptions = Log::DefaultOptions(L == LOG_CRITICAL)) {
|
||||
Init(aOptions, BasicLogger::ShouldOutputMessage(L));
|
||||
explicit Log(int aOptions = Log::DefaultOptions(L == LOG_CRITICAL),
|
||||
LogReason aReason = LogReason::MustBeMoreThanThis) {
|
||||
Init(aOptions, BasicLogger::ShouldOutputMessage(L), aReason);
|
||||
}
|
||||
|
||||
~Log() {
|
||||
@ -451,22 +469,30 @@ public:
|
||||
inline bool LogIt() const { return mLogIt; }
|
||||
inline bool NoNewline() const { return mOptions & int(LogOptions::NoNewline); }
|
||||
inline bool AutoPrefix() const { return mOptions & int(LogOptions::AutoPrefix); }
|
||||
inline bool ValidReason() const { return (int)mReason > (int)LogReason::MustBeMoreThanThis && (int)mReason < (int)LogReason::MustBeLessThanThis; }
|
||||
|
||||
// We do not want this version to do any work, and stringstream can't be
|
||||
// copied anyway. It does come in handy for the "Once" macro defined below.
|
||||
MOZ_IMPLICIT Log(const Log& log) { Init(log.mOptions, false); }
|
||||
MOZ_IMPLICIT Log(const Log& log) { Init(log.mOptions, false, log.mReason); }
|
||||
|
||||
private:
|
||||
// Initialization common to two constructors
|
||||
void Init(int aOptions, bool aLogIt) {
|
||||
void Init(int aOptions, bool aLogIt, LogReason aReason) {
|
||||
mOptions = aOptions;
|
||||
mReason = aReason;
|
||||
mLogIt = aLogIt;
|
||||
if (mLogIt && AutoPrefix()) {
|
||||
if (mOptions & int(LogOptions::AssertOnCall)) {
|
||||
mMessage << "[GFX" << L << "]: ";
|
||||
} else {
|
||||
mMessage << "[GFX" << L << "-]: ";
|
||||
if (mLogIt) {
|
||||
if (AutoPrefix()) {
|
||||
if (mOptions & int(LogOptions::AssertOnCall)) {
|
||||
mMessage << "[GFX" << L;
|
||||
} else {
|
||||
mMessage << "[GFX" << L << "-";
|
||||
}
|
||||
}
|
||||
if ((mOptions & int(LogOptions::CrashAction)) && ValidReason()) {
|
||||
mMessage << " " << (int)mReason;
|
||||
}
|
||||
mMessage << "]: ";
|
||||
}
|
||||
}
|
||||
|
||||
@ -476,11 +502,15 @@ private:
|
||||
if (mOptions & int(LogOptions::AssertOnCall)) {
|
||||
MOZ_ASSERT(false, "An assert from the graphics logger");
|
||||
}
|
||||
if ((mOptions & int(LogOptions::CrashAction)) && ValidReason()) {
|
||||
Logger::CrashAction(mReason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream mMessage;
|
||||
int mOptions;
|
||||
LogReason mReason;
|
||||
bool mLogIt;
|
||||
};
|
||||
|
||||
@ -531,6 +561,14 @@ typedef Log<LOG_CRITICAL, CriticalLogger> CriticalLog;
|
||||
#define gfxWarningOnce if (1) ; else mozilla::gfx::NoLog
|
||||
#endif
|
||||
|
||||
// In the debug build, this is equivalent to the default gfxCriticalError.
|
||||
// In the non-debug build, on nightly and dev edition, it will MOZ_CRASH.
|
||||
// On beta and release versions, it will telemetry count, but proceed.
|
||||
//
|
||||
// You should create a (new) enum in the LogReason and use it for the reason
|
||||
// parameter to ensure uniqueness.
|
||||
#define gfxCrash(reason) gfxCriticalError(int(LogOptions::AutoPrefix) | int(LogOptions::AssertOnCall) | int(LogOptions::CrashAction), (reason))
|
||||
|
||||
// See nsDebug.h and the NS_WARN_IF macro
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "mozilla/layers/ImageBridgeChild.h"
|
||||
#include "mozilla/layers/SharedBufferManagerChild.h"
|
||||
#include "mozilla/layers/ISurfaceAllocator.h" // for GfxMemoryImageReporter
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Services.h"
|
||||
@ -185,6 +186,7 @@ class CrashStatsLogForwarder: public mozilla::gfx::LogForwarder
|
||||
public:
|
||||
explicit CrashStatsLogForwarder(const char* aKey);
|
||||
virtual void Log(const std::string& aString) override;
|
||||
virtual void CrashAction(LogReason aReason) override;
|
||||
|
||||
virtual std::vector<std::pair<int32_t,std::string> > StringsVectorCopy() override;
|
||||
|
||||
@ -282,6 +284,55 @@ void CrashStatsLogForwarder::Log(const std::string& aString)
|
||||
}
|
||||
}
|
||||
|
||||
class CrashTelemetryEvent : public nsRunnable
|
||||
{
|
||||
virtual ~CrashTelemetryEvent() {}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
explicit CrashTelemetryEvent(uint32_t aReason) : mReason(aReason) {}
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
Telemetry::Accumulate(Telemetry::GFX_CRASH, mReason);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32_t mReason;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(CrashTelemetryEvent, nsRunnable);
|
||||
|
||||
void
|
||||
CrashStatsLogForwarder::CrashAction(LogReason aReason)
|
||||
{
|
||||
#ifndef RELEASE_BUILD
|
||||
// Non-release builds crash by default, but will use telemetry
|
||||
// if this environment variable is present.
|
||||
static bool useTelemetry = getenv("MOZ_GFX_CRASH_TELEMETRY") != 0;
|
||||
#else
|
||||
// Release builds use telemetry bu default, but will crash
|
||||
// if this environment variable is present. Double negative
|
||||
// to make the intent clear.
|
||||
static bool useTelemetry = !(getenv("MOZ_GFX_CRASH_MOZ_CRASH") != 0);
|
||||
#endif
|
||||
|
||||
if (useTelemetry) {
|
||||
// The callers need to assure that aReason is in the range
|
||||
// that the telemetry call below supports.
|
||||
if (NS_IsMainThread()) {
|
||||
Telemetry::Accumulate(Telemetry::GFX_CRASH, (uint32_t)aReason);
|
||||
} else {
|
||||
nsCOMPtr<nsIRunnable> r1 = new CrashTelemetryEvent((uint32_t)aReason);
|
||||
NS_DispatchToMainThread(r1);
|
||||
}
|
||||
} else {
|
||||
// ignoring aReason, we can get the information we need from the stack
|
||||
MOZ_CRASH("GFX_CRASH");
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(SRGBOverrideObserver, nsIObserver, nsISupportsWeakReference)
|
||||
|
||||
#define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
|
||||
@ -755,7 +806,7 @@ gfxPlatform::CreateDrawTargetForUpdateSurface(gfxASurface *aSurface, const IntSi
|
||||
return Factory::CreateDrawTargetForCairoCGContext(static_cast<gfxQuartzSurface*>(aSurface)->GetCGContext(), aSize);
|
||||
}
|
||||
#endif
|
||||
MOZ_CRASH();
|
||||
MOZ_CRASH("unused function");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -9851,6 +9851,13 @@
|
||||
"kind": "count",
|
||||
"description": "Number of times the D3D11 compositor failed to get a texture sync handle."
|
||||
},
|
||||
"GFX_CRASH": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "enumerated",
|
||||
"n_values": 100,
|
||||
"releaseChannelCollection": "opt-out",
|
||||
"description": "Graphics Crash Reason (...)"
|
||||
},
|
||||
"PLUGIN_ACTIVATION_COUNT": {
|
||||
"alert_emails": ["cpeterson@mozilla.com"],
|
||||
"expires_in_version": "48",
|
||||
|
Loading…
Reference in New Issue
Block a user