зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1483248 Part 1 - Allow recording child processes to handle TabChild deletion, r=mccr8.
--HG-- extra : rebase_source : 3f320c950c5018d0852b434a55d552a2e77c0f51
This commit is contained in:
Родитель
f4be588d5b
Коммит
3570b01c28
|
@ -44,6 +44,7 @@
|
|||
#include "mozilla/layout/RenderFrameChild.h"
|
||||
#include "mozilla/layout/RenderFrameParent.h"
|
||||
#include "mozilla/plugins/PPluginWidgetChild.h"
|
||||
#include "mozilla/recordreplay/ParentIPC.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
#include "mozilla/Move.h"
|
||||
|
@ -340,7 +341,10 @@ private:
|
|||
}
|
||||
|
||||
// Check in case ActorDestroy was called after RecvDestroy message.
|
||||
if (mTabChild->IPCOpen()) {
|
||||
// Middleman processes with their own recording child process avoid
|
||||
// sending a delete message, so that the parent process does not
|
||||
// receive two deletes for the same actor.
|
||||
if (mTabChild->IPCOpen() && !recordreplay::parent::IsMiddlemanWithRecordingChild()) {
|
||||
Unused << PBrowserChild::Send__delete__(mTabChild);
|
||||
}
|
||||
|
||||
|
|
|
@ -146,6 +146,12 @@ ParentProcessId()
|
|||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
bool
|
||||
IsMiddlemanWithRecordingChild()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace parent
|
||||
|
||||
} // namespace recordreplay
|
||||
|
|
|
@ -18,79 +18,12 @@ namespace mozilla {
|
|||
namespace recordreplay {
|
||||
namespace parent {
|
||||
|
||||
// Known associations between managee and manager routing IDs.
|
||||
static StaticInfallibleVector<std::pair<int32_t, int32_t>> gProtocolManagers;
|
||||
|
||||
// The routing IDs of actors in the parent process that have been destroyed.
|
||||
static StaticInfallibleVector<int32_t> gDeadRoutingIds;
|
||||
|
||||
static void
|
||||
NoteProtocolManager(int32_t aManagee, int32_t aManager)
|
||||
{
|
||||
gProtocolManagers.emplaceBack(aManagee, aManager);
|
||||
for (auto id : gDeadRoutingIds) {
|
||||
if (id == aManager) {
|
||||
gDeadRoutingIds.emplaceBack(aManagee);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DestroyRoutingId(int32_t aId)
|
||||
{
|
||||
gDeadRoutingIds.emplaceBack(aId);
|
||||
for (auto manager : gProtocolManagers) {
|
||||
if (manager.second == aId) {
|
||||
DestroyRoutingId(manager.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return whether a message from the child process to the UI process is being
|
||||
// sent to a target that is being destroyed, and should be suppressed.
|
||||
static bool
|
||||
MessageTargetIsDead(const IPC::Message& aMessage)
|
||||
{
|
||||
// After the parent process destroys a browser, we handle the destroy in
|
||||
// both the middleman and child processes. Both processes will respond to
|
||||
// the destroy by sending additional messages to the UI process indicating
|
||||
// the browser has been destroyed, but we need to ignore such messages from
|
||||
// the child process (if it is still recording) to avoid confusing the UI
|
||||
// process.
|
||||
for (int32_t id : gDeadRoutingIds) {
|
||||
if (id == aMessage.routing_id()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
HandleMessageInMiddleman(ipc::Side aSide, const IPC::Message& aMessage)
|
||||
{
|
||||
IPC::Message::msgid_t type = aMessage.type();
|
||||
|
||||
// Ignore messages sent from the child to dead UI process targets.
|
||||
if (aSide == ipc::ParentSide) {
|
||||
// When the browser is destroyed in the UI process all its children will
|
||||
// also be destroyed. Figure out the routing IDs of children which we need
|
||||
// to recognize as dead once the browser is destroyed. This is not a
|
||||
// complete list of all the browser's children, but only includes ones
|
||||
// where crashes have been seen as a result.
|
||||
if (type == dom::PBrowser::Msg_PDocAccessibleConstructor__ID) {
|
||||
PickleIterator iter(aMessage);
|
||||
ipc::ActorHandle handle;
|
||||
|
||||
if (!IPC::ReadParam(&aMessage, &iter, &handle))
|
||||
MOZ_CRASH("IPC::ReadParam failed");
|
||||
|
||||
NoteProtocolManager(handle.mId, aMessage.routing_id());
|
||||
}
|
||||
|
||||
if (MessageTargetIsDead(aMessage)) {
|
||||
PrintSpew("Suppressing %s message to dead target\n", IPC::StringFromIPCMessageType(type));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -144,9 +77,6 @@ HandleMessageInMiddleman(ipc::Side aSide, const IPC::Message& aMessage)
|
|||
// Preferences are initialized via the SetXPCOMProcessAttributes message.
|
||||
PreferencesLoaded();
|
||||
}
|
||||
if (type == dom::PBrowser::Msg_Destroy__ID) {
|
||||
DestroyRoutingId(aMessage.routing_id());
|
||||
}
|
||||
if (type == dom::PBrowser::Msg_RenderLayers__ID) {
|
||||
// Graphics are being loaded or unloaded for a tab, so update what we are
|
||||
// showing to the UI process according to the last paint performed.
|
||||
|
@ -277,7 +207,6 @@ public:
|
|||
|
||||
virtual Result OnMessageReceived(const Message& aMessage, Message*& aReply) override {
|
||||
MOZ_RELEASE_ASSERT(mOppositeMessageLoop);
|
||||
MOZ_RELEASE_ASSERT(mSide == ipc::ChildSide || !MessageTargetIsDead(aMessage));
|
||||
|
||||
Message* nMessage = new Message();
|
||||
nMessage->CopyFrom(aMessage);
|
||||
|
@ -314,7 +243,6 @@ public:
|
|||
|
||||
virtual Result OnCallReceived(const Message& aMessage, Message*& aReply) override {
|
||||
MOZ_RELEASE_ASSERT(mOppositeMessageLoop);
|
||||
MOZ_RELEASE_ASSERT(mSide == ipc::ChildSide || !MessageTargetIsDead(aMessage));
|
||||
|
||||
Message* nMessage = new Message();
|
||||
nMessage->CopyFrom(aMessage);
|
||||
|
|
|
@ -187,6 +187,12 @@ Shutdown()
|
|||
_exit(0);
|
||||
}
|
||||
|
||||
bool
|
||||
IsMiddlemanWithRecordingChild()
|
||||
{
|
||||
return IsMiddleman() && gRecordingChild;
|
||||
}
|
||||
|
||||
static ChildProcessInfo*
|
||||
OtherReplayingChild(ChildProcessInfo* aChild)
|
||||
{
|
||||
|
|
|
@ -40,6 +40,10 @@ const char* SaveAllRecordingsDirectory();
|
|||
// Get the pid of the UI process.
|
||||
base::ProcessId ParentProcessId();
|
||||
|
||||
// Return whether this is a middleman process that forwards IPDL messages to
|
||||
// a recording child process.
|
||||
bool IsMiddlemanWithRecordingChild();
|
||||
|
||||
// Save the recording up to the current point in execution.
|
||||
void SaveRecording(const ipc::FileDescriptor& aFile);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче