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:
Brian Hackett 2018-07-24 15:46:38 +00:00
Родитель de349302f2
Коммит 83d770739d
7 изменённых файлов: 25 добавлений и 74 удалений

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

@ -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,