Bug 1563832 - Move a few things into BaseProcessLauncher. r=jld

I'm not convinced the current comment about being race-free is accurate
in context of the launcher pool. It probably _is_ correct under this
patch, because ProcessLaunchers should only be constructed on a single
thread, but it's easy enough just to make it atomic.

Hopefully moving the timestamp doesn't perturb telemetry too much.

Differential Revision: https://phabricator.services.mozilla.com/D37305

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Bobby Holley 2019-07-11 15:27:51 +00:00
Родитель 9eac67a792
Коммит 6be1da5376
1 изменённых файлов: 52 добавлений и 55 удалений

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

@ -106,6 +106,8 @@ static bool ShouldHaveDirectoryService() {
namespace mozilla { namespace mozilla {
namespace ipc { namespace ipc {
static Atomic<int32_t> gChildCounter;
class BaseProcessLauncher { class BaseProcessLauncher {
public: public:
BaseProcessLauncher(GeckoChildProcessHost* aHost, BaseProcessLauncher(GeckoChildProcessHost* aHost,
@ -122,7 +124,9 @@ class BaseProcessLauncher {
mIsFileContent(aHost->mIsFileContent), mIsFileContent(aHost->mIsFileContent),
mEnableSandboxLogging(aHost->mEnableSandboxLogging), mEnableSandboxLogging(aHost->mEnableSandboxLogging),
#endif #endif
mTmpDirName(aHost->mTmpDirName) { mTmpDirName(aHost->mTmpDirName),
mChildId(++gChildCounter) {
SprintfLiteral(mPidString, "%d", base::GetCurrentProcId());
} }
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BaseProcessLauncher); NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BaseProcessLauncher);
@ -136,6 +140,12 @@ class BaseProcessLauncher {
static BinPathType GetPathToBinary(FilePath&, GeckoProcessType); static BinPathType GetPathToBinary(FilePath&, GeckoProcessType);
void GetChildLogName(const char* origLogName, nsACString& buffer);
const char* ChildProcessType() {
return XRE_ChildProcessTypeToString(mProcessType);
}
#if defined(MOZ_WIDGET_ANDROID) #if defined(MOZ_WIDGET_ANDROID)
void LaunchAndroidService( void LaunchAndroidService(
const char* type, const std::vector<std::string>& argv, const char* type, const std::vector<std::string>& argv,
@ -156,10 +166,16 @@ class BaseProcessLauncher {
bool mEnableSandboxLogging; bool mEnableSandboxLogging;
#endif #endif
nsCString mTmpDirName; nsCString mTmpDirName;
LaunchResults mResults = LaunchResults();
int32_t mChildId;
TimeStamp mStartTimeStamp = TimeStamp::Now();
char mPidString[32];
// Set during launch. // Set during launch.
IPC::Channel* mChannel = nullptr; IPC::Channel* mChannel = nullptr;
std::wstring mChannelId; std::wstring mChannelId;
ScopedPRFileDesc mCrashAnnotationReadPipe;
ScopedPRFileDesc mCrashAnnotationWritePipe;
}; };
#ifdef XP_WIN #ifdef XP_WIN
@ -663,9 +679,8 @@ void GeckoChildProcessHost::SetAlreadyDead() {
mChildProcessHandle = 0; mChildProcessHandle = 0;
} }
static int32_t gChildCounter = 0; void BaseProcessLauncher::GetChildLogName(const char* origLogName,
nsACString& buffer) {
static void GetChildLogName(const char* origLogName, nsACString& buffer) {
#ifdef XP_WIN #ifdef XP_WIN
// On Windows we must expand relative paths because sandboxing rules // On Windows we must expand relative paths because sandboxing rules
// bound only to full paths. fopen fowards to NtCreateFile which checks // bound only to full paths. fopen fowards to NtCreateFile which checks
@ -846,12 +861,6 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
}); });
#endif #endif
const auto startTS = TimeStamp::Now();
// - Note: this code is not called re-entrantly, nor are restoreOrig*LogName
// or gChildCounter touched by any other thread, so this is safe.
++gChildCounter;
const char* origNSPRLogName = PR_GetEnv("NSPR_LOG_FILE"); const char* origNSPRLogName = PR_GetEnv("NSPR_LOG_FILE");
const char* origMozLogName = PR_GetEnv("MOZ_LOG_FILE"); const char* origMozLogName = PR_GetEnv("MOZ_LOG_FILE");
@ -887,21 +896,8 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
} }
#endif #endif
LaunchResults results = LaunchResults(); if (PR_CreatePipe(&mCrashAnnotationReadPipe.rwget(),
results.mHandle = 0; &mCrashAnnotationWritePipe.rwget()) != PR_SUCCESS) {
// send the child the PID so that it can open a ProcessHandle back to us.
// probably don't want to do this in the long run
char pidstring[32];
SprintfLiteral(pidstring, "%d", base::GetCurrentProcId());
const char* const childProcessType =
XRE_ChildProcessTypeToString(mProcessType);
ScopedPRFileDesc crashAnnotationReadPipe;
ScopedPRFileDesc crashAnnotationWritePipe;
if (PR_CreatePipe(&crashAnnotationReadPipe.rwget(),
&crashAnnotationWritePipe.rwget()) != PR_SUCCESS) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__); return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
} }
@ -1018,7 +1014,7 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
AddAppDirToCommandLine(childArgv); AddAppDirToCommandLine(childArgv);
} }
childArgv.push_back(pidstring); childArgv.push_back(mPidString);
if (!CrashReporter::IsDummy()) { if (!CrashReporter::IsDummy()) {
# if defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS) # if defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
@ -1043,7 +1039,7 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
# endif // defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS) # endif // defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
} }
int fd = PR_FileDesc2NativeHandle(crashAnnotationWritePipe); int fd = PR_FileDesc2NativeHandle(mCrashAnnotationWritePipe);
mLaunchOptions->fds_to_remap.push_back( mLaunchOptions->fds_to_remap.push_back(
std::make_pair(fd, CrashReporter::GetAnnotationTimeCrashFd())); std::make_pair(fd, CrashReporter::GetAnnotationTimeCrashFd()));
@ -1059,7 +1055,7 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
childArgv.push_back(mach_connection_name.c_str()); childArgv.push_back(mach_connection_name.c_str());
# endif // MOZ_WIDGET_COCOA # endif // MOZ_WIDGET_COCOA
childArgv.push_back(childProcessType); childArgv.push_back(ChildProcessType());
# ifdef MOZ_WIDGET_COCOA # ifdef MOZ_WIDGET_COCOA
// Register the listening port before launching the child, to ensure // Register the listening port before launching the child, to ensure
@ -1068,13 +1064,13 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
# endif // MOZ_WIDGET_COCOA # endif // MOZ_WIDGET_COCOA
# if defined(MOZ_WIDGET_ANDROID) # if defined(MOZ_WIDGET_ANDROID)
LaunchAndroidService(childProcessType, childArgv, LaunchAndroidService(ChildProcessType(), childArgv,
mLaunchOptions->fds_to_remap, &results.mHandle); mLaunchOptions->fds_to_remap, &mResults.mHandle);
if (results.mHandle == 0) { if (mResults.mHandle == 0) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__); return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
} }
# else // goes with defined(MOZ_WIDGET_ANDROID) # else // goes with defined(MOZ_WIDGET_ANDROID)
if (!base::LaunchApp(childArgv, *mLaunchOptions, &results.mHandle)) { if (!base::LaunchApp(childArgv, *mLaunchOptions, &mResults.mHandle)) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__); return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
} }
# endif // defined(MOZ_WIDGET_ANDROID) # endif // defined(MOZ_WIDGET_ANDROID)
@ -1155,7 +1151,7 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
} }
SharedMemoryBasic::SetupMachMemory( SharedMemoryBasic::SetupMachMemory(
results.mHandle, parent_recv_port_memory, parent_recv_port_memory_ack, mResults.mHandle, parent_recv_port_memory, parent_recv_port_memory_ack,
parent_send_port_memory, parent_send_port_memory_ack, false); parent_send_port_memory, parent_send_port_memory_ack, false);
# endif // MOZ_WIDGET_COCOA # endif // MOZ_WIDGET_COCOA
@ -1215,10 +1211,10 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
# if defined(MOZ_SANDBOX) # if defined(MOZ_SANDBOX)
# if defined(_ARM64_) # if defined(_ARM64_)
if (isClearKey || isWidevine) if (isClearKey || isWidevine)
results.mSandboxBroker = new RemoteSandboxBroker(); mResults.mSandboxBroker = new RemoteSandboxBroker();
else else
# endif // if defined(_ARM64_) # endif // if defined(_ARM64_)
results.mSandboxBroker = new SandboxBroker(); mResults.mSandboxBroker = new SandboxBroker();
bool shouldSandboxCurrentProcess = false; bool shouldSandboxCurrentProcess = false;
@ -1232,14 +1228,14 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
// SetSecurityLevelForContentProcess and just crash there right away. // SetSecurityLevelForContentProcess and just crash there right away.
// Should this change in the future then we should also handle the error // Should this change in the future then we should also handle the error
// here. // here.
results.mSandboxBroker->SetSecurityLevelForContentProcess( mResults.mSandboxBroker->SetSecurityLevelForContentProcess(
mSandboxLevel, mIsFileContent); mSandboxLevel, mIsFileContent);
shouldSandboxCurrentProcess = true; shouldSandboxCurrentProcess = true;
} }
break; break;
case GeckoProcessType_Plugin: case GeckoProcessType_Plugin:
if (mSandboxLevel > 0 && !PR_GetEnv("MOZ_DISABLE_NPAPI_SANDBOX")) { if (mSandboxLevel > 0 && !PR_GetEnv("MOZ_DISABLE_NPAPI_SANDBOX")) {
bool ok = results.mSandboxBroker->SetSecurityLevelForPluginProcess( bool ok = mResults.mSandboxBroker->SetSecurityLevelForPluginProcess(
mSandboxLevel); mSandboxLevel);
if (!ok) { if (!ok) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__); return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
@ -1258,7 +1254,7 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
// so use sandbox level USER_RESTRICTED instead of USER_LOCKDOWN. // so use sandbox level USER_RESTRICTED instead of USER_LOCKDOWN.
auto level = auto level =
isWidevine ? SandboxBroker::Restricted : SandboxBroker::LockDown; isWidevine ? SandboxBroker::Restricted : SandboxBroker::LockDown;
bool ok = results.mSandboxBroker->SetSecurityLevelForGMPlugin(level); bool ok = mResults.mSandboxBroker->SetSecurityLevelForGMPlugin(level);
if (!ok) { if (!ok) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__); return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
} }
@ -1270,7 +1266,7 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
// For now we treat every failure as fatal in // For now we treat every failure as fatal in
// SetSecurityLevelForGPUProcess and just crash there right away. Should // SetSecurityLevelForGPUProcess and just crash there right away. Should
// this change in the future then we should also handle the error here. // this change in the future then we should also handle the error here.
results.mSandboxBroker->SetSecurityLevelForGPUProcess(mSandboxLevel); mResults.mSandboxBroker->SetSecurityLevelForGPUProcess(mSandboxLevel);
shouldSandboxCurrentProcess = true; shouldSandboxCurrentProcess = true;
} }
break; break;
@ -1281,7 +1277,7 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
break; break;
case GeckoProcessType_RDD: case GeckoProcessType_RDD:
if (!PR_GetEnv("MOZ_DISABLE_RDD_SANDBOX")) { if (!PR_GetEnv("MOZ_DISABLE_RDD_SANDBOX")) {
if (!results.mSandboxBroker->SetSecurityLevelForRDDProcess()) { if (!mResults.mSandboxBroker->SetSecurityLevelForRDDProcess()) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__); return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
} }
shouldSandboxCurrentProcess = true; shouldSandboxCurrentProcess = true;
@ -1302,7 +1298,7 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
if (shouldSandboxCurrentProcess) { if (shouldSandboxCurrentProcess) {
for (auto it = mAllowedFilesRead.begin(); it != mAllowedFilesRead.end(); for (auto it = mAllowedFilesRead.begin(); it != mAllowedFilesRead.end();
++it) { ++it) {
results.mSandboxBroker->AllowReadFile(it->c_str()); mResults.mSandboxBroker->AllowReadFile(it->c_str());
} }
} }
# endif // defined(MOZ_SANDBOX) # endif // defined(MOZ_SANDBOX)
@ -1318,35 +1314,35 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
cmdLine.AppendLooseValue(mGroupId.get()); cmdLine.AppendLooseValue(mGroupId.get());
// Process id // Process id
cmdLine.AppendLooseValue(UTF8ToWide(pidstring)); cmdLine.AppendLooseValue(UTF8ToWide(mPidString));
cmdLine.AppendLooseValue( cmdLine.AppendLooseValue(
UTF8ToWide(CrashReporter::GetChildNotificationPipe())); UTF8ToWide(CrashReporter::GetChildNotificationPipe()));
if (!CrashReporter::IsDummy()) { if (!CrashReporter::IsDummy()) {
PROsfd h = PR_FileDesc2NativeHandle(crashAnnotationWritePipe); PROsfd h = PR_FileDesc2NativeHandle(mCrashAnnotationWritePipe);
mLaunchOptions->handles_to_inherit.push_back(reinterpret_cast<HANDLE>(h)); mLaunchOptions->handles_to_inherit.push_back(reinterpret_cast<HANDLE>(h));
std::string hStr = std::to_string(h); std::string hStr = std::to_string(h);
cmdLine.AppendLooseValue(UTF8ToWide(hStr)); cmdLine.AppendLooseValue(UTF8ToWide(hStr));
} }
// Process type // Process type
cmdLine.AppendLooseValue(UTF8ToWide(childProcessType)); cmdLine.AppendLooseValue(UTF8ToWide(ChildProcessType()));
# if defined(MOZ_SANDBOX) # if defined(MOZ_SANDBOX)
if (shouldSandboxCurrentProcess) { if (shouldSandboxCurrentProcess) {
// Mark the handles to inherit as inheritable. // Mark the handles to inherit as inheritable.
for (HANDLE h : mLaunchOptions->handles_to_inherit) { for (HANDLE h : mLaunchOptions->handles_to_inherit) {
results.mSandboxBroker->AddHandleToShare(h); mResults.mSandboxBroker->AddHandleToShare(h);
} }
if (results.mSandboxBroker->LaunchApp( if (mResults.mSandboxBroker->LaunchApp(
cmdLine.program().c_str(), cmdLine.command_line_string().c_str(), cmdLine.program().c_str(), cmdLine.command_line_string().c_str(),
mLaunchOptions->env_map, mProcessType, mEnableSandboxLogging, mLaunchOptions->env_map, mProcessType, mEnableSandboxLogging,
&results.mHandle)) { &mResults.mHandle)) {
EnvironmentLog("MOZ_PROCESS_LOG") EnvironmentLog("MOZ_PROCESS_LOG")
.print("==> process %d launched child process %d (%S)\n", .print("==> process %d launched child process %d (%S)\n",
base::GetCurrentProcId(), base::GetProcId(results.mHandle), base::GetCurrentProcId(), base::GetProcId(mResults.mHandle),
cmdLine.command_line_string().c_str()); cmdLine.command_line_string().c_str());
} else { } else {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__); return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
@ -1354,7 +1350,7 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
} else } else
# endif // defined(MOZ_SANDBOX) # endif // defined(MOZ_SANDBOX)
{ {
if (!base::LaunchApp(cmdLine, *mLaunchOptions, &results.mHandle)) { if (!base::LaunchApp(cmdLine, *mLaunchOptions, &mResults.mHandle)) {
return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__); return ProcessLaunchPromise::CreateAndReject(LaunchError{}, __func__);
} }
@ -1369,7 +1365,7 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
// No handle duplication necessary. // No handle duplication necessary.
break; break;
default: default:
if (!SandboxBroker::AddTargetPeer(results.mHandle)) { if (!SandboxBroker::AddTargetPeer(mResults.mHandle)) {
NS_WARNING("Failed to add child process as target peer."); NS_WARNING("Failed to add child process as target peer.");
} }
break; break;
@ -1381,20 +1377,21 @@ RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
# error Sorry # error Sorry
#endif // defined(OS_POSIX) #endif // defined(OS_POSIX)
MOZ_DIAGNOSTIC_ASSERT(results.mHandle); MOZ_DIAGNOSTIC_ASSERT(mResults.mHandle);
// NB: on OS X, we block much longer than we need to in order to // NB: on OS X, we block much longer than we need to in order to
// reach this call, waiting for the child process's task_t. The // reach this call, waiting for the child process's task_t. The
// best way to fix that is to refactor this file, hard. // best way to fix that is to refactor this file, hard.
#ifdef XP_MACOSX #ifdef XP_MACOSX
results.mChildTask = child_task; mResults.mChildTask = child_task;
#endif // XP_MACOSX #endif // XP_MACOSX
CrashReporter::RegisterChildCrashAnnotationFileDescriptor( CrashReporter::RegisterChildCrashAnnotationFileDescriptor(
base::GetProcId(results.mHandle), crashAnnotationReadPipe.forget()); base::GetProcId(mResults.mHandle), mCrashAnnotationReadPipe.forget());
Telemetry::AccumulateTimeDelta(Telemetry::CHILD_PROCESS_LAUNCH_MS, startTS); Telemetry::AccumulateTimeDelta(Telemetry::CHILD_PROCESS_LAUNCH_MS,
mStartTimeStamp);
return ProcessLaunchPromise::CreateAndResolve(results, __func__); return ProcessLaunchPromise::CreateAndResolve(mResults, __func__);
} }
bool GeckoChildProcessHost::OpenPrivilegedHandle(base::ProcessId aPid) { bool GeckoChildProcessHost::OpenPrivilegedHandle(base::ProcessId aPid) {