feat: UtilityProcess API (#34980)

* chore: initial scaffolding

* chore: implement interface and docs

* chore: address code style review

* fix: cleanup of utility process on shutdown

* chore: simplify NodeBindings::CreateEnvironment

* chore: rename disableLibraryValidation => allowLoadingUnsignedLibraries

* chore: implement process.parentPort

* chore(posix): implement stdio pipe interface

* chore(win): implement stdio interface

* chore: reenable SetNodeOptions for utility process

* chore: add specs

* chore: fix lint

* fix: update kill API

* fix: update process.parentPort API

* fix: exit event

* docs: update exit event

* fix: tests on linux

* chore: expand on some comments

* fix: shutdown of pipe reader

Avoid logging since it is always the case that reader end of
pipe will terminate after the child process.

* fix: remove exit code check for crash spec

* fix: rm PR_SET_NO_NEW_PRIVS for unsandbox utility process

* chore: fix incorrect rebase

* fix: address review feedback

* chore: rename utility_process -> utility

* chore: update docs

* chore: cleanup c++ implemantation

* fix: leak in NodeServiceHost impl

* chore: minor cleanup

* chore: cleanup JS implementation

* chore: flip default stdio to inherit

* fix: some api improvements

* Support cwd option
* Remove path restriction for modulePath
* Rewire impl for env support

* fix: add tests for cwd and env option

* chore: alt impl for reading stdio handles

* chore: support message queuing

* chore: fix lint

* chore: new UtilityProcess => utilityProcess.fork

* fix: support for uncaught exception exits

* chore: remove process.execArgv as default

* fix: windows build

* fix: style changes

* fix: docs and style changes

* chore: update patches

* spec: disable flaky test on win32 arm CI

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
This commit is contained in:
Robo 2022-10-20 14:49:49 +09:00 committed by GitHub
parent 44c40efecf
commit da0fd286b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
59 changed files with 2700 additions and 54 deletions

View file

@ -24,13 +24,17 @@
#include "components/os_crypt/key_storage_config_linux.h"
#include "components/os_crypt/os_crypt.h"
#include "content/browser/browser_main_loop.h" // nogncheck
#include "content/public/browser/browser_child_process_host_delegate.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/device_service.h"
#include "content/public/browser/first_party_sets_handler.h"
#include "content/public/browser/web_ui_controller_factory.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/process_type.h"
#include "content/public/common/result_codes.h"
#include "electron/buildflags/buildflags.h"
#include "electron/fuses.h"
@ -39,6 +43,7 @@
#include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h"
#include "shell/app/electron_main_delegate.h"
#include "shell/browser/api/electron_api_app.h"
#include "shell/browser/api/electron_api_utility_process.h"
#include "shell/browser/browser.h"
#include "shell/browser/browser_process_impl.h"
#include "shell/browser/electron_browser_client.h"
@ -273,12 +278,15 @@ void ElectronBrowserMainParts::PostEarlyInitialization() {
// Add Electron extended APIs.
electron_bindings_->BindTo(js_env_->isolate(), env->process_object());
// Load everything.
node_bindings_->LoadEnvironment(env);
// Create explicit microtasks runner.
js_env_->CreateMicrotasksRunner();
// Wrap the uv loop with global env.
node_bindings_->set_uv_env(env);
// Load everything.
node_bindings_->LoadEnvironment(env);
// We already initialized the feature list in PreEarlyInitialization(), but
// the user JS script would not have had a chance to alter the command-line
// switches at that point. Lets reinitialize it here to pick up the
@ -503,7 +511,6 @@ int ElectronBrowserMainParts::PreMainMessageLoopRun() {
void ElectronBrowserMainParts::WillRunMainMessageLoop(
std::unique_ptr<base::RunLoop>& run_loop) {
js_env_->OnMessageLoopCreated();
exit_code_ = content::RESULT_CODE_NORMAL_EXIT;
Browser::Get()->SetMainMessageLoopQuitClosure(
run_loop->QuitWhenIdleClosure());
@ -565,10 +572,39 @@ void ElectronBrowserMainParts::PostMainMessageLoopRun() {
}
}
// Shutdown utility process created with Electron API before
// stopping Node.js so that exit events can be emitted. We don't let
// content layer perform this action since it destroys
// child process only after this step (PostMainMessageLoopRun) via
// BrowserProcessIOThread::ProcessHostCleanUp() which is too late for our
// use case.
// https://source.chromium.org/chromium/chromium/src/+/main:content/browser/browser_main_loop.cc;l=1086-1108
//
// The following logic is based on
// https://source.chromium.org/chromium/chromium/src/+/main:content/browser/browser_process_io_thread.cc;l=127-159
//
// Although content::BrowserChildProcessHostIterator is only to be called from
// IO thread, it is safe to call from PostMainMessageLoopRun because thread
// restrictions have been lifted.
// https://source.chromium.org/chromium/chromium/src/+/main:content/browser/browser_main_loop.cc;l=1062-1078
for (content::BrowserChildProcessHostIterator it(
content::PROCESS_TYPE_UTILITY);
!it.Done(); ++it) {
if (it.GetDelegate()->GetServiceName() == node::mojom::NodeService::Name_) {
auto& process = it.GetData().GetProcess();
if (!process.IsValid())
continue;
auto utility_process_wrapper =
api::UtilityProcessWrapper::FromProcessId(process.Pid());
if (utility_process_wrapper)
utility_process_wrapper->Shutdown(0 /* exit_code */);
}
}
// Destroy node platform after all destructors_ are executed, as they may
// invoke Node/V8 APIs inside them.
node_env_->env()->set_trace_sync_io(false);
js_env_->OnMessageLoopDestroying();
js_env_->DestroyMicrotasksRunner();
node::Stop(node_env_->env());
node_env_.reset();