зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1740619 - Include the launcher process in a Job object when "--wait-for-browser" is set. r=mhowell
When the launcher process is enabled, Puppeteer, or any other automation tools, cannot have control of the lifetime of the browser process even though the `--wait-for-browser` option is used. This patch is to include the launcher process and the browser process to a job to enable a launcher of the launcher process like Puppeteer to terminate the application by terminating the launcher process if `--wait-for-browser` is set. Differential Revision: https://phabricator.services.mozilla.com/D131170
This commit is contained in:
Родитель
7f3e52cd43
Коммит
68dd038b3b
|
@ -49,6 +49,34 @@ static mozilla::LauncherVoidResult PostCreationSetup(
|
|||
aChildProcess);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Job object and assign |aProcess| to it. If something fails
|
||||
* in this function, we return nullptr but continue without recording
|
||||
* a launcher failure because it's not a critical problem to launch
|
||||
* the browser process.
|
||||
*/
|
||||
static nsReturnRef<HANDLE> CreateJobAndAssignProcess(HANDLE aProcess) {
|
||||
nsAutoHandle empty;
|
||||
nsAutoHandle job(::CreateJobObjectW(nullptr, nullptr));
|
||||
|
||||
// Set JOB_OBJECT_LIMIT_BREAKAWAY_OK to allow the browser process
|
||||
// to put child processes into a job on Win7, which does not support
|
||||
// nested jobs. See CanUseJob() in sandboxBroker.cpp.
|
||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo = {};
|
||||
jobInfo.BasicLimitInformation.LimitFlags =
|
||||
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_BREAKAWAY_OK;
|
||||
if (!::SetInformationJobObject(job.get(), JobObjectExtendedLimitInformation,
|
||||
&jobInfo, sizeof(jobInfo))) {
|
||||
return empty.out();
|
||||
}
|
||||
|
||||
if (!::AssignProcessToJobObject(job.get(), aProcess)) {
|
||||
return empty.out();
|
||||
}
|
||||
|
||||
return job.out();
|
||||
}
|
||||
|
||||
#if !defined( \
|
||||
PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON)
|
||||
# define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON \
|
||||
|
@ -390,6 +418,11 @@ Maybe<int> LauncherMain(int& argc, wchar_t* argv[],
|
|||
nsAutoHandle process(pi.hProcess);
|
||||
nsAutoHandle mainThread(pi.hThread);
|
||||
|
||||
nsAutoHandle job;
|
||||
if (flags & LauncherFlags::eWaitForBrowser) {
|
||||
job = CreateJobAndAssignProcess(process.get());
|
||||
}
|
||||
|
||||
LauncherVoidResult setupResult = PostCreationSetup(
|
||||
argv[0], process.get(), mainThread.get(), isSafeMode.value());
|
||||
if (setupResult.isErr()) {
|
||||
|
|
|
@ -64,6 +64,50 @@ static wchar_t** AllocConvertUTF8toUTF16Strings(int argc, char** argv) {
|
|||
return argvConverted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if we are in a job with JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE and
|
||||
* we can break away from it.
|
||||
* CreateProcess fails if we try to break away from a job but it's not allowed.
|
||||
* So if we cannot determine the result due to a failure, we assume we don't
|
||||
* need to break away and this returns false.
|
||||
*/
|
||||
static bool NeedToBreakAwayFromJob() {
|
||||
// If we can't determine if we are in a job, we assume we're not in a job.
|
||||
BOOL inJob = FALSE;
|
||||
if (!::IsProcessInJob(::GetCurrentProcess(), nullptr, &inJob)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there is no job, there is nothing to worry about.
|
||||
if (!inJob) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we can't get the job object flags, we assume no need to break away from
|
||||
// it.
|
||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info = {};
|
||||
if (!::QueryInformationJobObject(nullptr, JobObjectExtendedLimitInformation,
|
||||
&job_info, sizeof(job_info), nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE is not set, no need to worry about
|
||||
// the job.
|
||||
if (!(job_info.BasicLimitInformation.LimitFlags &
|
||||
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we can't break away from the current job, there is nothing we can do.
|
||||
if (!(job_info.BasicLimitInformation.LimitFlags &
|
||||
JOB_OBJECT_LIMIT_BREAKAWAY_OK)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We can and need to break away from the job.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch a child process with the specified arguments.
|
||||
* @note argv[0] is ignored
|
||||
|
@ -92,6 +136,9 @@ BOOL WinLaunchChild(const wchar_t* exePath, int argc, wchar_t** argv,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD creationFlags =
|
||||
NeedToBreakAwayFromJob() ? CREATE_BREAKAWAY_FROM_JOB : 0;
|
||||
|
||||
STARTUPINFOW si = {0};
|
||||
si.cb = sizeof(STARTUPINFOW);
|
||||
si.lpDesktop = const_cast<LPWSTR>(L"winsta0\\Default");
|
||||
|
@ -102,7 +149,7 @@ BOOL WinLaunchChild(const wchar_t* exePath, int argc, wchar_t** argv,
|
|||
nullptr, // no special security attributes
|
||||
nullptr, // no special thread attributes
|
||||
FALSE, // don't inherit filehandles
|
||||
0, // creation flags
|
||||
creationFlags,
|
||||
nullptr, // inherit my environment
|
||||
nullptr, // use my current directory
|
||||
&si, &pi);
|
||||
|
@ -118,8 +165,7 @@ BOOL WinLaunchChild(const wchar_t* exePath, int argc, wchar_t** argv,
|
|||
nullptr, // no special security attributes
|
||||
nullptr, // no special thread attributes
|
||||
FALSE, // don't inherit filehandles
|
||||
0, // creation flags
|
||||
environmentBlock,
|
||||
creationFlags, environmentBlock,
|
||||
nullptr, // use my current directory
|
||||
&si, &pi);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче