Bug 1483248 Part 1 - Allow recording child processes to handle TabChild deletion, r=mccr8.

--HG--
extra : rebase_source : 3f320c950c5018d0852b434a55d552a2e77c0f51
This commit is contained in:
Brian Hackett 2018-08-21 00:58:31 +00:00
Родитель f4be588d5b
Коммит 3570b01c28
5 изменённых файлов: 21 добавлений и 73 удалений

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

@ -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);