mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-03 15:19:44 +00:00
Bug 1408086 - Append log of the latest 2 sets of composition events when ContentCacheInParent::OnEventNeedingAckHandled() meets unexpected state and crash itself r=m_kato
We have a lot of crash reports in OnEventNeedingAckHandled() due to unexpected state (hit MOZ_RELEASE_ASSERT). However, it's unclear what occurs and we're not sure there are how many cases to crash because the stack trace is too short because the method is called when TabParent receives event handled message from the remote process. I.e., it doesn't show what happens immediately before the crash. This patch puts 2 sets of composition events to app notes of crash report when it needs to crash. This *might* make damage to the performance. If so, after fixing the crashes, we should back this out. Fortunately, we have a lot of reports from either Nightly or Beta. MozReview-Commit-ID: 9tDrEIf72MG --HG-- extra : rebase_source : 523c183466740e08d6c8cc3836b6b52310c1e53a
This commit is contained in:
parent
7d84c84a7a
commit
929e66153e
@ -15,6 +15,9 @@
|
||||
#include "mozilla/TextComposition.h"
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#include "nsExceptionHandler.h"
|
||||
#endif // #ifdef MOZ_CRASHREPORTER
|
||||
#include "nsIWidget.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -1110,6 +1113,10 @@ ContentCacheInParent::OnCompositionEvent(const WidgetCompositionEvent& aEvent)
|
||||
GetBoolName(mWidgetHasComposition), mPendingCompositionCount,
|
||||
mCommitStringByRequest));
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
mDispatchedEventMessages.AppendElement(aEvent.mMessage);
|
||||
#endif // #ifdef MOZ_CRASHREPORTER
|
||||
|
||||
// We must be able to simulate the selection because
|
||||
// we might not receive selection updates in time
|
||||
if (!mWidgetHasComposition) {
|
||||
@ -1186,6 +1193,10 @@ ContentCacheInParent::OnSelectionEvent(
|
||||
GetBoolName(aSelectionEvent.mUseNativeLineBreak), mPendingEventsNeedingAck,
|
||||
GetBoolName(mWidgetHasComposition), mPendingCompositionCount));
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
mDispatchedEventMessages.AppendElement(aSelectionEvent.mMessage);
|
||||
#endif // #ifdef MOZ_CRASHREPORTER
|
||||
|
||||
mPendingEventsNeedingAck++;
|
||||
}
|
||||
|
||||
@ -1201,9 +1212,30 @@ ContentCacheInParent::OnEventNeedingAckHandled(nsIWidget* aWidget,
|
||||
"aMessage=%s), mPendingEventsNeedingAck=%u, mPendingCompositionCount=%" PRIu8,
|
||||
this, aWidget, ToChar(aMessage), mPendingEventsNeedingAck, mPendingCompositionCount));
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
mReceivedEventMessages.AppendElement(aMessage);
|
||||
#endif // #ifdef MOZ_CRASHREPORTER
|
||||
|
||||
if (WidgetCompositionEvent::IsFollowedByCompositionEnd(aMessage) ||
|
||||
aMessage == eCompositionCommitRequestHandled) {
|
||||
MOZ_RELEASE_ASSERT(mPendingCompositionCount > 0);
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
if (mPendingCompositionCount == 1) {
|
||||
RemoveUnnecessaryEventMessageLog();
|
||||
}
|
||||
#endif // #ifdef MOZ_CRASHREPORTER
|
||||
|
||||
if (NS_WARN_IF(!mPendingCompositionCount)) {
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
nsPrintfCString info("There is no pending composition but received %s "
|
||||
"message from the remote child\n\n",
|
||||
ToChar(aMessage));
|
||||
AppendEventMessageLog(info);
|
||||
CrashReporter::AppendAppNotesToCrashReport(info);
|
||||
#endif // #ifdef MOZ_CRASHREPORTER
|
||||
MOZ_CRASH("No pending composition but received unexpected commit event");
|
||||
}
|
||||
|
||||
mPendingCompositionCount--;
|
||||
// Forget composition string only when the latest composition string is
|
||||
// handled in the remote process because if there is 2 or more pending
|
||||
@ -1219,7 +1251,16 @@ ContentCacheInParent::OnEventNeedingAckHandled(nsIWidget* aWidget,
|
||||
mPendingCommitLength = 0;
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(mPendingEventsNeedingAck > 0);
|
||||
if (NS_WARN_IF(!mPendingEventsNeedingAck)) {
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
nsPrintfCString info("There is no pending events but received %s "
|
||||
"message from the remote child\n\n",
|
||||
ToChar(aMessage));
|
||||
AppendEventMessageLog(info);
|
||||
CrashReporter::AppendAppNotesToCrashReport(info);
|
||||
#endif // #ifdef MOZ_CRASHREPORTER
|
||||
MOZ_CRASH("No pending event message but received unexpected event");
|
||||
}
|
||||
if (--mPendingEventsNeedingAck) {
|
||||
return;
|
||||
}
|
||||
@ -1409,6 +1450,61 @@ ContentCacheInParent::FlushPendingNotifications(nsIWidget* aWidget)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
|
||||
void
|
||||
ContentCacheInParent::RemoveUnnecessaryEventMessageLog()
|
||||
{
|
||||
bool foundLastCompositionStart = false;
|
||||
for (size_t i = mDispatchedEventMessages.Length(); i > 1; i--) {
|
||||
if (mDispatchedEventMessages[i - 1] != eCompositionStart) {
|
||||
continue;
|
||||
}
|
||||
if (!foundLastCompositionStart) {
|
||||
// Find previous eCompositionStart of the latest eCompositionStart.
|
||||
foundLastCompositionStart = true;
|
||||
continue;
|
||||
}
|
||||
// Remove the messages before the last 2 sets of composition events.
|
||||
mDispatchedEventMessages.RemoveElementsAt(0, i - 1);
|
||||
break;
|
||||
}
|
||||
foundLastCompositionStart = false;
|
||||
for (size_t i = mReceivedEventMessages.Length(); i > 1; i--) {
|
||||
if (mReceivedEventMessages[i - 1] != eCompositionStart) {
|
||||
continue;
|
||||
}
|
||||
if (!foundLastCompositionStart) {
|
||||
// Find previous eCompositionStart of the latest eCompositionStart.
|
||||
foundLastCompositionStart = true;
|
||||
continue;
|
||||
}
|
||||
// Remove the messages before the last 2 sets of composition events.
|
||||
mReceivedEventMessages.RemoveElementsAt(0, i - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContentCacheInParent::AppendEventMessageLog(nsACString& aLog) const
|
||||
{
|
||||
aLog.AppendLiteral("Dispatched Event Message Log:\n");
|
||||
for (EventMessage message : mDispatchedEventMessages) {
|
||||
aLog.AppendLiteral(" ");
|
||||
aLog.Append(ToChar(message));
|
||||
aLog.AppendLiteral("\n");
|
||||
}
|
||||
aLog.AppendLiteral("\nReceived Event Message Log:\n");
|
||||
for (EventMessage message : mReceivedEventMessages) {
|
||||
aLog.AppendLiteral(" ");
|
||||
aLog.Append(ToChar(message));
|
||||
aLog.AppendLiteral("\n");
|
||||
}
|
||||
aLog.AppendLiteral("\n");
|
||||
}
|
||||
|
||||
#endif // #ifdef MOZ_CRASHREPORTER
|
||||
|
||||
/*****************************************************************************
|
||||
* mozilla::ContentCache::TextRectArray
|
||||
*****************************************************************************/
|
||||
|
@ -410,6 +410,12 @@ private:
|
||||
IMENotification mPendingLayoutChange;
|
||||
IMENotification mPendingCompositionUpdate;
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
// Log of event messages to be output to crash report.
|
||||
nsTArray<EventMessage> mDispatchedEventMessages;
|
||||
nsTArray<EventMessage> mReceivedEventMessages;
|
||||
#endif // #ifdef MOZ_CRASHREPORTER
|
||||
|
||||
// mTabParent is owner of the instance.
|
||||
dom::TabParent& MOZ_NON_OWNING_REF mTabParent;
|
||||
// mCompositionString is composition string which were sent to the remote
|
||||
@ -464,6 +470,19 @@ private:
|
||||
LayoutDeviceIntRect& aUnionTextRect) const;
|
||||
|
||||
void FlushPendingNotifications(nsIWidget* aWidget);
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
/**
|
||||
* Remove unnecessary messages from mDispatchedEventMessages and
|
||||
* mReceivedEventMessages.
|
||||
*/
|
||||
void RemoveUnnecessaryEventMessageLog();
|
||||
|
||||
/**
|
||||
* Append event message log to aLog.
|
||||
*/
|
||||
void AppendEventMessageLog(nsACString& aLog) const;
|
||||
#endif // #ifdef MOZ_CRASHREPORTER
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
Loading…
x
Reference in New Issue
Block a user