зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1477561 - Improve handling of shared memory preference data when spawning recording processes, r=mccr8.
--HG-- extra : rebase_source : eddad711819ffb1783f9a02cefbe2d75fd6b8f68
This commit is contained in:
Родитель
de349302f2
Коммит
83d770739d
|
@ -262,32 +262,22 @@ ContentProcess::Init(int aArgc, char* aArgv[])
|
|||
return false;
|
||||
}
|
||||
|
||||
if (recordreplay::IsRecordingOrReplaying()) {
|
||||
// Set up early prefs from shmem contents passed to us by the middleman.
|
||||
Preferences::DeserializePreferences(recordreplay::child::PrefsShmemContents(*prefsLen),
|
||||
*prefsLen);
|
||||
} else {
|
||||
// Init the shared-memory base preference mapping first, so that only changed
|
||||
// preferences wind up in heap memory.
|
||||
Preferences::InitSnapshot(prefMapHandle.ref(), *prefMapSize);
|
||||
// Init the shared-memory base preference mapping first, so that only changed
|
||||
// preferences wind up in heap memory.
|
||||
Preferences::InitSnapshot(prefMapHandle.ref(), *prefMapSize);
|
||||
|
||||
// Set up early prefs from the shared memory.
|
||||
base::SharedMemory shm;
|
||||
if (!shm.SetHandle(*prefsHandle, /* read_only */ true)) {
|
||||
NS_ERROR("failed to open shared memory in the child");
|
||||
return false;
|
||||
}
|
||||
if (!shm.Map(*prefsLen)) {
|
||||
NS_ERROR("failed to map shared memory in the child");
|
||||
return false;
|
||||
}
|
||||
Preferences::DeserializePreferences(static_cast<char*>(shm.memory()),
|
||||
*prefsLen);
|
||||
if (recordreplay::IsMiddleman()) {
|
||||
recordreplay::parent::NotePrefsShmemContents(static_cast<char*>(shm.memory()),
|
||||
*prefsLen);
|
||||
}
|
||||
// Set up early prefs from the shared memory.
|
||||
base::SharedMemory shm;
|
||||
if (!shm.SetHandle(*prefsHandle, /* read_only */ true)) {
|
||||
NS_ERROR("failed to open shared memory in the child");
|
||||
return false;
|
||||
}
|
||||
if (!shm.Map(*prefsLen)) {
|
||||
NS_ERROR("failed to map shared memory in the child");
|
||||
return false;
|
||||
}
|
||||
Preferences::DeserializePreferences(static_cast<char*>(shm.memory()),
|
||||
*prefsLen);
|
||||
|
||||
Scheduler::SetPrefs(*schedulerPrefs);
|
||||
|
||||
|
|
|
@ -171,33 +171,25 @@ protected:
|
|||
struct IntroductionMessage : public Message
|
||||
{
|
||||
base::ProcessId mParentPid;
|
||||
uint32_t mPrefsLen;
|
||||
uint32_t mArgc;
|
||||
|
||||
IntroductionMessage(uint32_t aSize, base::ProcessId aParentPid, uint32_t aPrefsLen, uint32_t aArgc)
|
||||
IntroductionMessage(uint32_t aSize, base::ProcessId aParentPid, uint32_t aArgc)
|
||||
: Message(MessageType::Introduction, aSize)
|
||||
, mParentPid(aParentPid)
|
||||
, mPrefsLen(aPrefsLen)
|
||||
, mArgc(aArgc)
|
||||
{}
|
||||
|
||||
char* PrefsData() { return Data<IntroductionMessage, char>(); }
|
||||
char* ArgvString() { return Data<IntroductionMessage, char>() + mPrefsLen; }
|
||||
char* ArgvString() { return Data<IntroductionMessage, char>(); }
|
||||
const char* ArgvString() const { return Data<IntroductionMessage, char>(); }
|
||||
|
||||
const char* PrefsData() const { return Data<IntroductionMessage, char>(); }
|
||||
const char* ArgvString() const { return Data<IntroductionMessage, char>() + mPrefsLen; }
|
||||
|
||||
static IntroductionMessage* New(base::ProcessId aParentPid, char* aPrefs, size_t aPrefsLen,
|
||||
int aArgc, char* aArgv[]) {
|
||||
static IntroductionMessage* New(base::ProcessId aParentPid, int aArgc, char* aArgv[]) {
|
||||
size_t argsLen = 0;
|
||||
for (int i = 0; i < aArgc; i++) {
|
||||
argsLen += strlen(aArgv[i]) + 1;
|
||||
}
|
||||
|
||||
IntroductionMessage* res =
|
||||
NewWithData<IntroductionMessage, char>(aPrefsLen + argsLen, aParentPid, aPrefsLen, aArgc);
|
||||
|
||||
memcpy(res->PrefsData(), aPrefs, aPrefsLen);
|
||||
NewWithData<IntroductionMessage, char>(argsLen, aParentPid, aArgc);
|
||||
|
||||
size_t offset = 0;
|
||||
for (int i = 0; i < aArgc; i++) {
|
||||
|
|
|
@ -50,9 +50,6 @@ static base::ProcessId gMiddlemanPid;
|
|||
static base::ProcessId gParentPid;
|
||||
static StaticInfallibleVector<char*> gParentArgv;
|
||||
|
||||
static char* gShmemPrefs;
|
||||
static size_t gShmemPrefsLen;
|
||||
|
||||
// File descriptors used by a pipe to create checkpoints when instructed by the
|
||||
// parent process.
|
||||
static FileHandle gCheckpointWriteFd;
|
||||
|
@ -146,13 +143,6 @@ ChannelMessageHandler(Message* aMsg)
|
|||
free(aMsg);
|
||||
}
|
||||
|
||||
char*
|
||||
PrefsShmemContents(size_t aPrefsLen)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(aPrefsLen == gShmemPrefsLen);
|
||||
return gShmemPrefs;
|
||||
}
|
||||
|
||||
// Main routine for a thread whose sole purpose is to listen to requests from
|
||||
// the middleman process to create a new checkpoint. This is separate from the
|
||||
// channel thread because this thread is recorded and the latter is not
|
||||
|
@ -248,20 +238,15 @@ InitRecordingOrReplayingProcess(int* aArgc, char*** aArgv)
|
|||
HitCheckpoint(CheckpointId::Invalid, /* aRecordingEndpoint = */ false);
|
||||
|
||||
// Process the introduction message to fill in arguments.
|
||||
MOZ_RELEASE_ASSERT(!gShmemPrefs);
|
||||
MOZ_RELEASE_ASSERT(gParentArgv.empty());
|
||||
|
||||
gParentPid = gIntroductionMessage->mParentPid;
|
||||
|
||||
// Record/replay the introduction message itself so we get consistent args
|
||||
// and prefs between recording and replaying.
|
||||
// between recording and replaying.
|
||||
{
|
||||
IntroductionMessage* msg = IntroductionMessage::RecordReplay(*gIntroductionMessage);
|
||||
|
||||
gShmemPrefs = new char[msg->mPrefsLen];
|
||||
memcpy(gShmemPrefs, msg->PrefsData(), msg->mPrefsLen);
|
||||
gShmemPrefsLen = msg->mPrefsLen;
|
||||
|
||||
const char* pos = msg->ArgvString();
|
||||
for (size_t i = 0; i < msg->mArgc; i++) {
|
||||
gParentArgv.append(strdup(pos));
|
||||
|
|
|
@ -41,9 +41,6 @@ namespace child {
|
|||
// and is a no-op if the process is not recording/replaying.
|
||||
void InitRecordingOrReplayingProcess(int* aArgc, char*** aArgv);
|
||||
|
||||
// Get the contents of the prefs shmem as conveyed to the middleman process.
|
||||
char* PrefsShmemContents(size_t aPrefsLen);
|
||||
|
||||
base::ProcessId MiddlemanProcessId();
|
||||
base::ProcessId ParentProcessId();
|
||||
|
||||
|
|
|
@ -464,6 +464,10 @@ ChildProcessInfo::LaunchSubprocess()
|
|||
|
||||
MOZ_RELEASE_ASSERT(!gRecordingProcess);
|
||||
gRecordingProcess = new ipc::GeckoChildProcessHost(GeckoProcessType_Content);
|
||||
|
||||
gRecordingProcess->AddFdToRemap(kPrefsFileDescriptor, kPrefsFileDescriptor);
|
||||
gRecordingProcess->AddFdToRemap(kPrefMapFileDescriptor, kPrefMapFileDescriptor);
|
||||
|
||||
if (!gRecordingProcess->LaunchAndWaitForProcessHandle(extraArgs)) {
|
||||
MOZ_CRASH("ChildProcessInfo::LaunchSubprocess");
|
||||
}
|
||||
|
|
|
@ -829,28 +829,14 @@ MainThreadMessageLoop()
|
|||
return gMainThreadMessageLoop;
|
||||
}
|
||||
|
||||
// Contents of the prefs shmem block that is sent to the child on startup.
|
||||
static char* gShmemPrefs;
|
||||
static size_t gShmemPrefsLen;
|
||||
|
||||
void
|
||||
NotePrefsShmemContents(char* aPrefs, size_t aPrefsLen)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(!gShmemPrefs);
|
||||
gShmemPrefs = new char[aPrefsLen];
|
||||
memcpy(gShmemPrefs, aPrefs, aPrefsLen);
|
||||
gShmemPrefsLen = aPrefsLen;
|
||||
}
|
||||
|
||||
void
|
||||
InitializeMiddleman(int aArgc, char* aArgv[], base::ProcessId aParentPid)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(gShmemPrefs);
|
||||
|
||||
// Construct the message that will be sent to each child when starting up.
|
||||
IntroductionMessage* msg =
|
||||
IntroductionMessage::New(aParentPid, gShmemPrefs, gShmemPrefsLen, aArgc, aArgv);
|
||||
IntroductionMessage::New(aParentPid, aArgc, aArgv);
|
||||
ChildProcessInfo::SetIntroductionMessage(msg);
|
||||
|
||||
MOZ_RELEASE_ASSERT(gProcessKind == ProcessKind::MiddlemanRecording ||
|
||||
|
|
|
@ -45,9 +45,6 @@ ipc::MessageChannel* ChannelToUIProcess();
|
|||
// Initialize state in a middleman process.
|
||||
void InitializeMiddleman(int aArgc, char* aArgv[], base::ProcessId aParentPid);
|
||||
|
||||
// Note the contents of the prefs shmem for use by the child process.
|
||||
void NotePrefsShmemContents(char* aPrefs, size_t aPrefsLen);
|
||||
|
||||
// Open a socket which a recording/replaying child can use to connect to its
|
||||
// middleman process.
|
||||
void OpenChannel(base::ProcessId aMiddlemanPid, uint32_t aChannelId,
|
||||
|
|
Загрузка…
Ссылка в новой задаче