Bug 1503750 - Add preference to allow crashing on repaint failures, r=mccr8.

--HG--
extra : rebase_source : df926fba3f291e2a56975936d1090c7d0ce54c60
This commit is contained in:
Brian Hackett 2018-10-31 14:57:01 -10:00
Родитель 579aa6d5df
Коммит e3503a74b9
5 изменённых файлов: 40 добавлений и 10 удалений

Просмотреть файл

@ -1110,6 +1110,7 @@ pref("devtools.recordreplay.enableRewinding", true);
pref("devtools.recordreplay.mvp.enabled", false); pref("devtools.recordreplay.mvp.enabled", false);
pref("devtools.recordreplay.timeline.enabled", false); pref("devtools.recordreplay.timeline.enabled", false);
pref("devtools.recordreplay.allowRepaintFailures", true);
// view source // view source
pref("view_source.syntax_highlight", true); pref("view_source.syntax_highlight", true);

Просмотреть файл

@ -8,6 +8,7 @@
#include "InfallibleVector.h" #include "InfallibleVector.h"
#include "MiddlemanCall.h" #include "MiddlemanCall.h"
#include "ipc/ChildInternal.h"
#include "ipc/ParentInternal.h" #include "ipc/ParentInternal.h"
#include "mozilla/Sprintf.h" #include "mozilla/Sprintf.h"
@ -100,9 +101,11 @@ RecordReplayInterceptCall(int aCallId, CallArguments* aArguments)
} }
} }
if (parent::InRepaintStressMode()) { if (child::CurrentRepaintCannotFail()) {
// We're about to crash, so print out the name of the call that failed. // EnsureNotDivergedFromRecording is going to force us to crash, so fail
Print("Could not perform middleman call: %s\n", redirection.mName); // earlier with a more helpful error message.
child::ReportFatalError(Nothing(), "Could not perform middleman call: %s\n",
redirection.mName);
} }
// Calling any redirection which performs the standard steps will cause // Calling any redirection which performs the standard steps will cause

Просмотреть файл

@ -237,10 +237,10 @@ EnsureNotDivergedFromRecording()
if (HasDivergedFromRecording()) { if (HasDivergedFromRecording()) {
MOZ_RELEASE_ASSERT(gUnhandledDivergeAllowed); MOZ_RELEASE_ASSERT(gUnhandledDivergeAllowed);
// Crash instead of rewinding in the painting stress mode, for finding // Crash instead of rewinding if a repaint is about to fail and is not
// areas where middleman calls do not cover all painting logic. // allowed.
if (parent::InRepaintStressMode()) { if (child::CurrentRepaintCannotFail()) {
MOZ_CRASH("Recording divergence in repaint stress mode"); MOZ_CRASH("Recording divergence while repainting");
} }
PrintSpew("Unhandled recording divergence, restoring checkpoint...\n"); PrintSpew("Unhandled recording divergence, restoring checkpoint...\n");

Просмотреть файл

@ -475,6 +475,9 @@ static Atomic<int32_t, SequentiallyConsistent, Behavior::DontPreserve> gNumPendi
// ID of the compositor thread. // ID of the compositor thread.
static Atomic<size_t, SequentiallyConsistent, Behavior::DontPreserve> gCompositorThreadId; static Atomic<size_t, SequentiallyConsistent, Behavior::DontPreserve> gCompositorThreadId;
// Whether repaint failures are allowed, or if the process should crash.
static bool gAllowRepaintFailures;
already_AddRefed<gfx::DrawTarget> already_AddRefed<gfx::DrawTarget>
DrawTargetForRemoteDrawing(LayoutDeviceIntSize aSize) DrawTargetForRemoteDrawing(LayoutDeviceIntSize aSize)
{ {
@ -522,6 +525,17 @@ NotifyPaintStart()
{ {
MOZ_RELEASE_ASSERT(NS_IsMainThread()); MOZ_RELEASE_ASSERT(NS_IsMainThread());
// Initialize state on the first paint.
static bool gPainted;
if (!gPainted) {
gPainted = true;
// Repaint failures are not allowed in the repaint stress mode.
gAllowRepaintFailures =
Preferences::GetBool("devtools.recordreplay.allowRepaintFailures") &&
!parent::InRepaintStressMode();
}
// A new paint cannot be triggered until the last one finishes and has been // A new paint cannot be triggered until the last one finishes and has been
// sent to the middleman. // sent to the middleman.
MOZ_RELEASE_ASSERT(HasDivergedFromRecording() || !gHasActivePaint); MOZ_RELEASE_ASSERT(HasDivergedFromRecording() || !gHasActivePaint);
@ -571,6 +585,9 @@ NotifyPaintComplete()
// Whether we have repainted since diverging from the recording. // Whether we have repainted since diverging from the recording.
static bool gDidRepaint; static bool gDidRepaint;
// Whether we are currently repainting.
static bool gRepainting;
void void
Repaint(size_t* aWidth, size_t* aHeight) Repaint(size_t* aWidth, size_t* aHeight)
{ {
@ -588,6 +605,7 @@ Repaint(size_t* aWidth, size_t* aHeight)
// case the last graphics we sent will still be correct. // case the last graphics we sent will still be correct.
if (!gDidRepaint) { if (!gDidRepaint) {
gDidRepaint = true; gDidRepaint = true;
gRepainting = true;
// Allow other threads to diverge from the recording so the compositor can // Allow other threads to diverge from the recording so the compositor can
// perform any paint we are about to trigger, or finish any in flight paint // perform any paint we are about to trigger, or finish any in flight paint
@ -611,6 +629,7 @@ Repaint(size_t* aWidth, size_t* aHeight)
} }
Thread::WaitForIdleThreads(); Thread::WaitForIdleThreads();
gRepainting = false;
} }
if (gDrawTargetBuffer) { if (gDrawTargetBuffer) {
@ -623,6 +642,12 @@ Repaint(size_t* aWidth, size_t* aHeight)
} }
} }
bool
CurrentRepaintCannotFail()
{
return gRepainting && !gAllowRepaintFailures;
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Checkpoint Messages // Checkpoint Messages
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -115,9 +115,6 @@ void NotifyFlushedRecording();
// Notify the middleman about an AlwaysMarkMajorCheckpoints directive. // Notify the middleman about an AlwaysMarkMajorCheckpoints directive.
void NotifyAlwaysMarkMajorCheckpoints(); void NotifyAlwaysMarkMajorCheckpoints();
// Report a fatal error to the middleman process.
void ReportFatalError(const char* aFormat, ...);
// Mark a time span when the main thread is idle. // Mark a time span when the main thread is idle.
void BeginIdleTime(); void BeginIdleTime();
void EndIdleTime(); void EndIdleTime();
@ -130,6 +127,10 @@ void SendMiddlemanCallRequest(const char* aInputData, size_t aInputSize,
InfallibleVector<char>* aOutputData); InfallibleVector<char>* aOutputData);
void SendResetMiddlemanCalls(); void SendResetMiddlemanCalls();
// Return whether a repaint is in progress and is not allowed to trigger an
// unhandled recording divergence per preferences.
bool CurrentRepaintCannotFail();
} // namespace child } // namespace child
} // namespace recordreplay } // namespace recordreplay