mirror of
https://github.com/electron/electron.git
synced 2026-01-09 15:38:08 -05:00
* chore: bump chromium in DEPS to 104.0.5096.0 * 3651284: Use the entry settings object for window.open navigation https://chromium-review.googlesource.com/c/chromium/src/+/3651284 * 3644598: Make RenderFrameHost used for notification permission decision https://chromium-review.googlesource.com/c/chromium/src/+/3644598 * 3642842: Window Placement: Prototype Fullscreen Capability Delegation - Part 2 https://chromium-review.googlesource.com/c/chromium/src/+/3642842 * 3652785: [sandbox] Enable sandboxed pointers on sanitizer builds https://chromium-review.googlesource.com/c/v8/v8/+/3652785 * 3611967: webhid: Migrate HidDelegate to use BrowserContext and Origin https://chromium-review.googlesource.com/c/chromium/src/+/3611967 * 3665762: Remove RenderFrameHost::IsRenderFrameCreated from //content/. https://chromium-review.googlesource.com/c/chromium/src/+/3665762 * 3659375: Fold x509_util_ios and most of x509_util_mac into x509_util_apple https://chromium-review.googlesource.com/c/chromium/src/+/3659375 * 3656234: [CodeHealth] Remove uses of base::ListValue::Append() (Final, take 2) https://chromium-review.googlesource.com/c/chromium/src/+/3656234 * chore: update patch indices * chore: fix lint * 3644598: Make RenderFrameHost used for notification permission decision https://chromium-review.googlesource.com/c/chromium/src/+/3644598 * webhid: Migrate HidDelegate to use BrowserContext and Origin This is a temporary fix for https://chromium-review.googlesource.com/c/chromium/src/+/3611967 to get the build compiling, but we need to either patch around https://chromium-review.googlesource.com/c/chromium/src/+/3611967 or move our device permissioning to BrowserContext * chore: fix lint * build: run electron/script/gen-libc++-filenames.js fixes gn check * chore: bump chromium in DEPS to 104.0.5098.0 * chore: disable flaking tests * 3682394: Change pipes surrounding code references in comments to backticks https://chromium-review.googlesource.com/c/chromium/src/+/3682394 * 3652749: Delete GLRenderer and related classes https://chromium-review.googlesource.com/c/chromium/src/+/3652749 * chore: fixup patch indices * 3671199: Remove ContentMainDelegate::PostFieldTrialInitialization https://chromium-review.googlesource.com/c/chromium/src/+/3671199 * 3607963: hid: Do not exclude HID device with no collections https://chromium-review.googlesource.com/c/chromium/src/+/3607963 * refactor: use ElectronBrowserContext instead of WebContents to persist devices due to changes like https://chromium-review.googlesource.com/c/chromium/src/+/3611967, we can no longer use WebContents to store device permissions so this commit moves device permission storage to live in memory in ElectronBrowserContext instead. * 3557253: Deprecate some signature checks https://chromium-review.googlesource.com/c/v8/v8/+/3557253 * chore: bump chromium in DEPS to 104.0.5100.0 * 3680781: Add policy for Renderer App Container. https://chromium-review.googlesource.com/c/chromium/src/+/3680781 * chore: update patch indices * 3675465: Update NetLog network service API to use mojom::DictionaryValue. https://chromium-review.googlesource.com/c/chromium/src/+/3675465 * chore: bump chromium in DEPS to 104.0.5102.0 * chore: update patches * chore: bump chromium in DEPS to 104.0.5103.0 * chore: update patches * chore: bump chromium in DEPS to 104.0.5104.0 * chore: update patches * fix: add patch for DCHECK in fullscreen test * build: fix nan build * build: make the nan spec runner work on macOS * chore: bump chromium in DEPS to 104.0.5106.0 * chore: update patches * chore: bump chromium in DEPS to 104.0.5108.0 * chore: update patches * chore: bump chromium in DEPS to 104.0.5110.0 * chore: update patches * chore: bump chromium in DEPS to 104.0.5112.0 * chore: bump chromium in DEPS to 105.0.5113.0 * chore: bump chromium in DEPS to 105.0.5115.0 * chore: bump chromium in DEPS to 105.0.5117.0 * chore: update patches * chore: update libcpp patch * 3693745: Delete base::LowerCaseEqualsASCII() Ref: https://chromium-review.googlesource.com/c/chromium/src/+/3693745 * 3669226: Remove printing PostTask usage of IO thread Ref: https://chromium-review.googlesource.com/c/chromium/src/+/3669226 * 3687395: Remove DictionaryValue::HasKey(). Ref: https://chromium-review.googlesource.com/c/chromium/src/+/3687395 * 3691014: Prevent unsafe narrowing: ui/accessibility, part 2 Ref: https://chromium-review.googlesource.com/c/chromium/src/+/3691014 * 3560567: [MSC] Porting GenerateStreams clients to handle stream vectors. Ref: https://chromium-review.googlesource.com/c/chromium/src/+/3560567 * 3684873: [Bluetooth][Win/Linux] Add bluetooth pair confirmation prompt https://chromium-review.googlesource.com/c/chromium/src/+/3684873 * chore: bump chromium in DEPS to 105.0.5119.0 * chore: missing includes in desktop_notification_controller * chore: update patches * 3685951: Reland "Make sure screen object is created once in tests." https://chromium-review.googlesource.com/c/chromium/src/+/3685951 * fixup: Reland "Make sure screen object is created once in tests." * 3646014: [API] Deprecate LegacyOOMErrorCallback Ref: https://chromium-review.googlesource.com/c/v8/v8/+/3646014 * chore: bump chromium in DEPS to 105.0.5121.0 * chore: update patches * 3699085: [cleanup] update PrintBackend::EnumeratePrinters to use reference Ref: https://chromium-review.googlesource.com/c/chromium/src/+/3699085 * chore: bump chromium in DEPS to 105.0.5123.0 * chore: update patches * chore: bump chromium in DEPS to 105.0.5125.0 * chore: update patches * 3630082: [sandbox] Also enable the sandbox outside of Chromium builds Ref: https://chromium-review.googlesource.com/c/v8/v8/+/3630082 * chore: bump chromium in DEPS to 105.0.5127.0 * chore: update patches * chore: bump chromium in DEPS to 105.0.5129.0 * chore: update patches * 3703741: Remove WebContents::GetMainFrame. https://chromium-review.googlesource.com/c/chromium/src/+/3703741 * chore: update patches * fixup! 3703741: Remove WebContents::GetMainFrame. * fix lint * more lint * chore: document breaking change * 3687671: [v8] Freeze flags after initialization https://chromium-review.googlesource.com/c/chromium/src/+/3687671 * fixup! 3560567: [MSC] Porting GenerateStreams clients to handle stream vectors. * use the v8 allocator for node serdes * chore: update patches * remove faulty non-v8-sandbox-compatible code * make NodeArrayBufferAllocator use the v8 allocator under the hood * fixup! 3560567: [MSC] Porting GenerateStreams clients to handle stream vectors. * fix build on windows * 3691954: [Reland][Extensions Bindings] Validate arguments sent to API events https://chromium-review.googlesource.com/c/chromium/src/+/3691954 * chore: remove deprecated AccessorSignatures https://github.com/nodejs/nan/pull/941 * Update patches/chromium/notification_provenance.patch Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> * remove chore_expose_v8_initialization_isolate_callbacks.patch * add link to nodejs/nan#941 * 52026: Do not allow md4 or md5 based signatures in X.509 certificates. https://boringssl-review.googlesource.com/c/boringssl/+/52026 * chore: update patches * disable nan buffer-test * disable sandboxed pointers for now * force sandboxed pointers off * improve node allocation patch * restore accidentally dropped node crypto test patch Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> Co-authored-by: Charles Kerr <charles@charleskerr.com> Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com> Co-authored-by: Samuel Attard <sattard@salesforce.com> Co-authored-by: Keeley Hammond <khammond@slack-corp.com> Co-authored-by: VerteDinde <keeleymhammond@gmail.com> Co-authored-by: VerteDinde <vertedinde@electronjs.org> Co-authored-by: Jeremy Rose <jeremya@chromium.org> Co-authored-by: Jeremy Rose <japthorp@slack-corp.com>
642 lines
26 KiB
Diff
642 lines
26 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
From: Darshan Sen <raisinten@gmail.com>
|
||
Date: Fri, 17 Jun 2022 13:19:32 +0530
|
||
Subject: posix: Replace DoubleForkAndExec() with ForkAndSpawn()
|
||
|
||
The DoubleForkAndExec() function was taking over 622 milliseconds to run
|
||
on macOS 11 (BigSur) on Intel i5-1038NG7. I did some debugging by adding
|
||
some custom traces and found that the fork() syscall is the bottleneck
|
||
here, i.e., the first fork() takes around 359 milliseconds and the
|
||
nested fork() takes around 263 milliseconds. Replacing the nested fork()
|
||
and exec() with posix_spawn() reduces the time consumption to 257
|
||
milliseconds!
|
||
|
||
See https://github.com/libuv/libuv/pull/3064 to know why fork() is so
|
||
slow on macOS and why posix_spawn() is a better replacement.
|
||
|
||
Another point to note is that even base::LaunchProcess() from Chromium
|
||
calls posix_spawnp() on macOS -
|
||
https://source.chromium.org/chromium/chromium/src/+/8f8d82dea0fa8f11f57c74dbb65126f8daba58f7:base/process/launch_mac.cc;l=295-296
|
||
|
||
Change-Id: I25c6ee9629a1ae5d0c32b361b56a1ce0b4b0fd26
|
||
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3641386
|
||
Reviewed-by: Mark Mentovai <mark@chromium.org>
|
||
Commit-Queue: Mark Mentovai <mark@chromium.org>
|
||
|
||
diff --git a/third_party/crashpad/crashpad/AUTHORS b/third_party/crashpad/crashpad/AUTHORS
|
||
index 8dcac3238870920d374b86033d05d77ebde351e9..02103924332eddbd158c04f8a395bb4a247e8bd9 100644
|
||
--- a/third_party/crashpad/crashpad/AUTHORS
|
||
+++ b/third_party/crashpad/crashpad/AUTHORS
|
||
@@ -12,3 +12,4 @@ Opera Software ASA
|
||
Vewd Software AS
|
||
LG Electronics, Inc.
|
||
MIPS Technologies, Inc.
|
||
+Darshan Sen <raisinten@gmail.com>
|
||
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
|
||
index 295ec1615d83984835e238e349029b8755611f52..94c1cb02efe328ab45bc30fc7db8992872ed6b08 100644
|
||
--- a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
|
||
+++ b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
|
||
@@ -45,7 +45,7 @@
|
||
#include "util/linux/socket.h"
|
||
#include "util/misc/address_sanitizer.h"
|
||
#include "util/misc/from_pointer_cast.h"
|
||
-#include "util/posix/double_fork_and_exec.h"
|
||
+#include "util/posix/fork_and_spawn.h"
|
||
#include "util/posix/scoped_mmap.h"
|
||
#include "util/posix/signals.h"
|
||
|
||
@@ -459,7 +459,7 @@ bool CrashpadClient::StartHandler(
|
||
|
||
argv.push_back(FormatArgumentInt("initial-client-fd", handler_sock.get()));
|
||
argv.push_back("--shared-client-connection");
|
||
- if (!DoubleForkAndExec(argv, nullptr, handler_sock.get(), false, nullptr)) {
|
||
+ if (!ForkAndSpawn(argv, nullptr, handler_sock.get(), false, nullptr)) {
|
||
return false;
|
||
}
|
||
|
||
@@ -614,7 +614,7 @@ bool CrashpadClient::StartJavaHandlerForClient(
|
||
int socket) {
|
||
std::vector<std::string> argv = BuildAppProcessArgs(
|
||
class_name, database, metrics_dir, url, annotations, arguments, socket);
|
||
- return DoubleForkAndExec(argv, env, socket, false, nullptr);
|
||
+ return ForkAndSpawn(argv, env, socket, false, nullptr);
|
||
}
|
||
|
||
bool CrashpadClient::StartHandlerWithLinkerAtCrash(
|
||
@@ -663,7 +663,7 @@ bool CrashpadClient::StartHandlerWithLinkerForClient(
|
||
annotations,
|
||
arguments,
|
||
socket);
|
||
- return DoubleForkAndExec(argv, env, socket, false, nullptr);
|
||
+ return ForkAndSpawn(argv, env, socket, false, nullptr);
|
||
}
|
||
|
||
#endif
|
||
@@ -697,7 +697,7 @@ bool CrashpadClient::StartHandlerForClient(
|
||
|
||
argv.push_back(FormatArgumentInt("initial-client-fd", socket));
|
||
|
||
- return DoubleForkAndExec(argv, nullptr, socket, true, nullptr);
|
||
+ return ForkAndSpawn(argv, nullptr, socket, true, nullptr);
|
||
}
|
||
|
||
// static
|
||
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_mac.cc b/third_party/crashpad/crashpad/client/crashpad_client_mac.cc
|
||
index 39e35678ecdd036f8c8ae27c973c27102b77da96..84385f2569f2bd00ca8aed0aa332fb450b2de1d3 100644
|
||
--- a/third_party/crashpad/crashpad/client/crashpad_client_mac.cc
|
||
+++ b/third_party/crashpad/crashpad/client/crashpad_client_mac.cc
|
||
@@ -36,7 +36,7 @@
|
||
#include "util/mach/notify_server.h"
|
||
#include "util/misc/clock.h"
|
||
#include "util/misc/implicit_cast.h"
|
||
-#include "util/posix/double_fork_and_exec.h"
|
||
+#include "util/posix/fork_and_spawn.h"
|
||
|
||
namespace crashpad {
|
||
|
||
@@ -343,7 +343,7 @@ class HandlerStarter final : public NotifyServer::DefaultInterface {
|
||
// this parent process, which was probably using the exception server now
|
||
// being restarted. The handler can’t monitor itself for its own crashes via
|
||
// this interface.
|
||
- if (!DoubleForkAndExec(
|
||
+ if (!ForkAndSpawn(
|
||
argv,
|
||
nullptr,
|
||
server_write_fd.get(),
|
||
diff --git a/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc b/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc
|
||
index 9e58d94aa499fdb7271a78ea21a1dcc1b12e3a52..3caa3b987b35be575558a312026cf6f19485c418 100644
|
||
--- a/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc
|
||
+++ b/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc
|
||
@@ -29,7 +29,7 @@
|
||
#include "util/linux/ptrace_client.h"
|
||
#include "util/misc/metrics.h"
|
||
#include "util/misc/uuid.h"
|
||
-#include "util/posix/double_fork_and_exec.h"
|
||
+#include "util/posix/fork_and_spawn.h"
|
||
|
||
namespace crashpad {
|
||
|
||
@@ -266,12 +266,11 @@ bool CrosCrashReportExceptionHandler::HandleExceptionWithConnection(
|
||
argv.push_back("--always_allow_feedback");
|
||
}
|
||
|
||
- if (!DoubleForkAndExec(argv,
|
||
- nullptr /* envp */,
|
||
- file_writer.fd() /* preserve_fd */,
|
||
- false /* use_path */,
|
||
- nullptr /* child_function */)) {
|
||
- LOG(ERROR) << "DoubleForkAndExec failed";
|
||
+ if (!ForkAndSpawn(argv,
|
||
+ nullptr /* envp */,
|
||
+ file_writer.fd() /* preserve_fd */,
|
||
+ false /* use_path */,
|
||
+ nullptr /* child_function */)) {
|
||
Metrics::ExceptionCaptureResult(
|
||
Metrics::CaptureResult::kFinishedWritingCrashReportFailed);
|
||
return false;
|
||
diff --git a/third_party/crashpad/crashpad/util/BUILD.gn b/third_party/crashpad/crashpad/util/BUILD.gn
|
||
index b8daef48b460ce2771a9f5502ee48d5efffc4039..8d4329e6b56062a1ef48a8607ddf52c31d251883 100644
|
||
--- a/third_party/crashpad/crashpad/util/BUILD.gn
|
||
+++ b/third_party/crashpad/crashpad/util/BUILD.gn
|
||
@@ -296,10 +296,10 @@ crashpad_static_library("util") {
|
||
sources += [
|
||
"posix/close_multiple.cc",
|
||
"posix/close_multiple.h",
|
||
- "posix/double_fork_and_exec.cc",
|
||
- "posix/double_fork_and_exec.h",
|
||
"posix/drop_privileges.cc",
|
||
"posix/drop_privileges.h",
|
||
+ "posix/fork_and_spawn.cc",
|
||
+ "posix/fork_and_spawn.h",
|
||
"posix/process_info.h",
|
||
|
||
# These map signals to and from strings. While Fuchsia defines some of
|
||
diff --git a/third_party/crashpad/crashpad/util/posix/double_fork_and_exec.cc b/third_party/crashpad/crashpad/util/posix/double_fork_and_exec.cc
|
||
deleted file mode 100644
|
||
index 1960430954d3f6459dce688493db5c42047567b0..0000000000000000000000000000000000000000
|
||
--- a/third_party/crashpad/crashpad/util/posix/double_fork_and_exec.cc
|
||
+++ /dev/null
|
||
@@ -1,166 +0,0 @@
|
||
-// Copyright 2017 The Crashpad Authors. All rights reserved.
|
||
-//
|
||
-// Licensed under the Apache License, Version 2.0 (the "License");
|
||
-// you may not use this file except in compliance with the License.
|
||
-// You may obtain a copy of the License at
|
||
-//
|
||
-// http://www.apache.org/licenses/LICENSE-2.0
|
||
-//
|
||
-// Unless required by applicable law or agreed to in writing, software
|
||
-// distributed under the License is distributed on an "AS IS" BASIS,
|
||
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
-// See the License for the specific language governing permissions and
|
||
-// limitations under the License.
|
||
-
|
||
-#include "util/posix/double_fork_and_exec.h"
|
||
-
|
||
-#include <stdlib.h>
|
||
-#include <string.h>
|
||
-#include <sys/wait.h>
|
||
-#include <unistd.h>
|
||
-
|
||
-#include "base/check_op.h"
|
||
-#include "base/logging.h"
|
||
-#include "base/posix/eintr_wrapper.h"
|
||
-#include "base/strings/stringprintf.h"
|
||
-#include "util/posix/close_multiple.h"
|
||
-
|
||
-namespace crashpad {
|
||
-
|
||
-bool DoubleForkAndExec(const std::vector<std::string>& argv,
|
||
- const std::vector<std::string>* envp,
|
||
- int preserve_fd,
|
||
- bool use_path,
|
||
- void (*child_function)()) {
|
||
- DCHECK(!envp || !use_path);
|
||
-
|
||
- // argv_c contains const char* pointers and is terminated by nullptr. This is
|
||
- // suitable for passing to execv(). Although argv_c is not used in the parent
|
||
- // process, it must be built in the parent process because it’s unsafe to do
|
||
- // so in the child or grandchild process.
|
||
- std::vector<const char*> argv_c;
|
||
- argv_c.reserve(argv.size() + 1);
|
||
- for (const std::string& argument : argv) {
|
||
- argv_c.push_back(argument.c_str());
|
||
- }
|
||
- argv_c.push_back(nullptr);
|
||
-
|
||
- std::vector<const char*> envp_c;
|
||
- if (envp) {
|
||
- envp_c.reserve(envp->size() + 1);
|
||
- for (const std::string& variable : *envp) {
|
||
- envp_c.push_back(variable.c_str());
|
||
- }
|
||
- envp_c.push_back(nullptr);
|
||
- }
|
||
-
|
||
- // Double-fork(). The three processes involved are parent, child, and
|
||
- // grandchild. The grandchild will call execv(). The child exits immediately
|
||
- // after spawning the grandchild, so the grandchild becomes an orphan and its
|
||
- // parent process ID becomes 1. This relieves the parent and child of the
|
||
- // responsibility to reap the grandchild with waitpid() or similar. The
|
||
- // grandchild is expected to outlive the parent process, so the parent
|
||
- // shouldn’t be concerned with reaping it. This approach means that accidental
|
||
- // early termination of the handler process will not result in a zombie
|
||
- // process.
|
||
- pid_t pid = fork();
|
||
- if (pid < 0) {
|
||
- PLOG(ERROR) << "fork";
|
||
- return false;
|
||
- }
|
||
-
|
||
- if (pid == 0) {
|
||
- // Child process.
|
||
-
|
||
- if (child_function) {
|
||
- child_function();
|
||
- }
|
||
-
|
||
- // Call setsid(), creating a new process group and a new session, both led
|
||
- // by this process. The new process group has no controlling terminal. This
|
||
- // disconnects it from signals generated by the parent process’ terminal.
|
||
- //
|
||
- // setsid() is done in the child instead of the grandchild so that the
|
||
- // grandchild will not be a session leader. If it were a session leader, an
|
||
- // accidental open() of a terminal device without O_NOCTTY would make that
|
||
- // terminal the controlling terminal.
|
||
- //
|
||
- // It’s not desirable for the grandchild to have a controlling terminal. The
|
||
- // grandchild manages its own lifetime, such as by monitoring clients on its
|
||
- // own and exiting when it loses all clients and when it deems it
|
||
- // appropraite to do so. It may serve clients in different process groups or
|
||
- // sessions than its original client, and receiving signals intended for its
|
||
- // original client’s process group could be harmful in that case.
|
||
- PCHECK(setsid() != -1) << "setsid";
|
||
-
|
||
- pid = fork();
|
||
- if (pid < 0) {
|
||
- PLOG(FATAL) << "fork";
|
||
- }
|
||
-
|
||
- if (pid > 0) {
|
||
- // Child process.
|
||
-
|
||
- // _exit() instead of exit(), because fork() was called.
|
||
- _exit(EXIT_SUCCESS);
|
||
- }
|
||
-
|
||
- // Grandchild process.
|
||
-
|
||
- CloseMultipleNowOrOnExec(STDERR_FILENO + 1, preserve_fd);
|
||
-
|
||
- // &argv_c[0] is a pointer to a pointer to const char data, but because of
|
||
- // how C (not C++) works, execvp() wants a pointer to a const pointer to
|
||
- // char data. It modifies neither the data nor the pointers, so the
|
||
- // const_cast is safe.
|
||
- char* const* argv_for_execv = const_cast<char* const*>(&argv_c[0]);
|
||
-
|
||
- if (envp) {
|
||
- // This cast is safe for the same reason that the argv_for_execv cast is.
|
||
- char* const* envp_for_execv = const_cast<char* const*>(&envp_c[0]);
|
||
- execve(argv_for_execv[0], argv_for_execv, envp_for_execv);
|
||
- PLOG(FATAL) << "execve " << argv_for_execv[0];
|
||
- }
|
||
-
|
||
- if (use_path) {
|
||
- execvp(argv_for_execv[0], argv_for_execv);
|
||
- PLOG(FATAL) << "execvp " << argv_for_execv[0];
|
||
- }
|
||
-
|
||
- execv(argv_for_execv[0], argv_for_execv);
|
||
- PLOG(FATAL) << "execv " << argv_for_execv[0];
|
||
- }
|
||
-
|
||
- // waitpid() for the child, so that it does not become a zombie process. The
|
||
- // child normally exits quickly.
|
||
- //
|
||
- // Failures from this point on may result in the accumulation of a zombie, but
|
||
- // should not be considered fatal. Log only warnings, but don’t treat these
|
||
- // failures as a failure of the function overall.
|
||
- int status;
|
||
- pid_t wait_pid = HANDLE_EINTR(waitpid(pid, &status, 0));
|
||
- if (wait_pid == -1) {
|
||
- PLOG(WARNING) << "waitpid";
|
||
- return true;
|
||
- }
|
||
- DCHECK_EQ(wait_pid, pid);
|
||
-
|
||
- if (WIFSIGNALED(status)) {
|
||
- int sig = WTERMSIG(status);
|
||
- LOG(WARNING) << base::StringPrintf(
|
||
- "intermediate process terminated by signal %d (%s)%s",
|
||
- sig,
|
||
- strsignal(sig),
|
||
- WCOREDUMP(status) ? " (core dumped)" : "");
|
||
- } else if (!WIFEXITED(status)) {
|
||
- LOG(WARNING) << base::StringPrintf(
|
||
- "intermediate process: unknown termination 0x%x", status);
|
||
- } else if (WEXITSTATUS(status) != EXIT_SUCCESS) {
|
||
- LOG(WARNING) << "intermediate process exited with code "
|
||
- << WEXITSTATUS(status);
|
||
- }
|
||
-
|
||
- return true;
|
||
-}
|
||
-
|
||
-} // namespace crashpad
|
||
diff --git a/third_party/crashpad/crashpad/util/posix/fork_and_spawn.cc b/third_party/crashpad/crashpad/util/posix/fork_and_spawn.cc
|
||
new file mode 100644
|
||
index 0000000000000000000000000000000000000000..c6a95bbfdcba45995b0034789c8bdb4423a25642
|
||
--- /dev/null
|
||
+++ b/third_party/crashpad/crashpad/util/posix/fork_and_spawn.cc
|
||
@@ -0,0 +1,235 @@
|
||
+// Copyright 2017 The Crashpad Authors. All rights reserved.
|
||
+//
|
||
+// Licensed under the Apache License, Version 2.0 (the "License");
|
||
+// you may not use this file except in compliance with the License.
|
||
+// You may obtain a copy of the License at
|
||
+//
|
||
+// http://www.apache.org/licenses/LICENSE-2.0
|
||
+//
|
||
+// Unless required by applicable law or agreed to in writing, software
|
||
+// distributed under the License is distributed on an "AS IS" BASIS,
|
||
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
+// See the License for the specific language governing permissions and
|
||
+// limitations under the License.
|
||
+
|
||
+#include "util/posix/fork_and_spawn.h"
|
||
+
|
||
+#include <errno.h>
|
||
+#include <spawn.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <sys/wait.h>
|
||
+#include <unistd.h>
|
||
+
|
||
+#include "base/check.h"
|
||
+#include "base/check_op.h"
|
||
+#include "base/logging.h"
|
||
+#include "base/posix/eintr_wrapper.h"
|
||
+#include "base/strings/stringprintf.h"
|
||
+#include "build/build_config.h"
|
||
+#include "util/posix/close_multiple.h"
|
||
+
|
||
+extern char** environ;
|
||
+
|
||
+namespace crashpad {
|
||
+
|
||
+namespace {
|
||
+
|
||
+#if BUILDFLAG(IS_APPLE)
|
||
+
|
||
+class PosixSpawnAttr {
|
||
+ public:
|
||
+ PosixSpawnAttr() {
|
||
+ PCHECK((errno = posix_spawnattr_init(&attr_)) == 0)
|
||
+ << "posix_spawnattr_init";
|
||
+ }
|
||
+
|
||
+ PosixSpawnAttr(const PosixSpawnAttr&) = delete;
|
||
+ PosixSpawnAttr& operator=(const PosixSpawnAttr&) = delete;
|
||
+
|
||
+ ~PosixSpawnAttr() {
|
||
+ PCHECK((errno = posix_spawnattr_destroy(&attr_)) == 0)
|
||
+ << "posix_spawnattr_destroy";
|
||
+ }
|
||
+
|
||
+ void SetFlags(short flags) {
|
||
+ PCHECK((errno = posix_spawnattr_setflags(&attr_, flags)) == 0)
|
||
+ << "posix_spawnattr_setflags";
|
||
+ }
|
||
+
|
||
+ const posix_spawnattr_t* Get() const { return &attr_; }
|
||
+
|
||
+ private:
|
||
+ posix_spawnattr_t attr_;
|
||
+};
|
||
+
|
||
+class PosixSpawnFileActions {
|
||
+ public:
|
||
+ PosixSpawnFileActions() {
|
||
+ PCHECK((errno = posix_spawn_file_actions_init(&file_actions_)) == 0)
|
||
+ << "posix_spawn_file_actions_init";
|
||
+ }
|
||
+
|
||
+ PosixSpawnFileActions(const PosixSpawnFileActions&) = delete;
|
||
+ PosixSpawnFileActions& operator=(const PosixSpawnFileActions&) = delete;
|
||
+
|
||
+ ~PosixSpawnFileActions() {
|
||
+ PCHECK((errno = posix_spawn_file_actions_destroy(&file_actions_)) == 0)
|
||
+ << "posix_spawn_file_actions_destroy";
|
||
+ }
|
||
+
|
||
+ void AddInheritedFileDescriptor(int fd) {
|
||
+ PCHECK((errno = posix_spawn_file_actions_addinherit_np(&file_actions_,
|
||
+ fd)) == 0)
|
||
+ << "posix_spawn_file_actions_addinherit_np";
|
||
+ }
|
||
+
|
||
+ const posix_spawn_file_actions_t* Get() const { return &file_actions_; }
|
||
+
|
||
+ private:
|
||
+ posix_spawn_file_actions_t file_actions_;
|
||
+};
|
||
+
|
||
+#endif
|
||
+
|
||
+} // namespace
|
||
+
|
||
+bool ForkAndSpawn(const std::vector<std::string>& argv,
|
||
+ const std::vector<std::string>* envp,
|
||
+ int preserve_fd,
|
||
+ bool use_path,
|
||
+ void (*child_function)()) {
|
||
+ // argv_c contains const char* pointers and is terminated by nullptr. This is
|
||
+ // suitable for passing to posix_spawn() or posix_spawnp(). Although argv_c is
|
||
+ // not used in the parent process, it must be built in the parent process
|
||
+ // because it’s unsafe to do so in the child.
|
||
+ std::vector<const char*> argv_c;
|
||
+ argv_c.reserve(argv.size() + 1);
|
||
+ for (const std::string& argument : argv) {
|
||
+ argv_c.push_back(argument.c_str());
|
||
+ }
|
||
+ argv_c.push_back(nullptr);
|
||
+
|
||
+ std::vector<const char*> envp_c;
|
||
+ if (envp) {
|
||
+ envp_c.reserve(envp->size() + 1);
|
||
+ for (const std::string& variable : *envp) {
|
||
+ envp_c.push_back(variable.c_str());
|
||
+ }
|
||
+ envp_c.push_back(nullptr);
|
||
+ }
|
||
+
|
||
+ // The three processes involved are parent, child, and grandchild. The child
|
||
+ // exits immediately after spawning the grandchild, so the grandchild becomes
|
||
+ // an orphan and its parent process ID becomes 1. This relieves the parent and
|
||
+ // child of the responsibility to reap the grandchild with waitpid() or
|
||
+ // similar. The grandchild is expected to outlive the parent process, so the
|
||
+ // parent shouldn’t be concerned with reaping it. This approach means that
|
||
+ // accidental early termination of the handler process will not result in a
|
||
+ // zombie process.
|
||
+ pid_t pid = fork();
|
||
+ if (pid < 0) {
|
||
+ PLOG(ERROR) << "fork";
|
||
+ return false;
|
||
+ }
|
||
+
|
||
+ if (pid == 0) {
|
||
+ // Child process.
|
||
+
|
||
+ if (child_function) {
|
||
+ child_function();
|
||
+ }
|
||
+
|
||
+ // Call setsid(), creating a new process group and a new session, both led
|
||
+ // by this process. The new process group has no controlling terminal. This
|
||
+ // disconnects it from signals generated by the parent process’ terminal.
|
||
+ //
|
||
+ // setsid() is done in the child instead of the grandchild so that the
|
||
+ // grandchild will not be a session leader. If it were a session leader, an
|
||
+ // accidental open() of a terminal device without O_NOCTTY would make that
|
||
+ // terminal the controlling terminal.
|
||
+ //
|
||
+ // It’s not desirable for the grandchild to have a controlling terminal. The
|
||
+ // grandchild manages its own lifetime, such as by monitoring clients on its
|
||
+ // own and exiting when it loses all clients and when it deems it
|
||
+ // appropraite to do so. It may serve clients in different process groups or
|
||
+ // sessions than its original client, and receiving signals intended for its
|
||
+ // original client’s process group could be harmful in that case.
|
||
+ PCHECK(setsid() != -1) << "setsid";
|
||
+
|
||
+ // &argv_c[0] is a pointer to a pointer to const char data, but because of
|
||
+ // how C (not C++) works, posix_spawn() and posix_spawnp() want a pointer to
|
||
+ // a const pointer to char data. They modifies neither the data nor the
|
||
+ // pointers, so the const_cast is safe.
|
||
+ char* const* argv_for_spawn = const_cast<char* const*>(argv_c.data());
|
||
+
|
||
+ // This cast is safe for the same reason that the argv_for_spawn cast is.
|
||
+ char* const* envp_for_spawn =
|
||
+ envp ? const_cast<char* const*>(envp_c.data()) : environ;
|
||
+
|
||
+#if BUILDFLAG(IS_APPLE)
|
||
+ PosixSpawnAttr attr;
|
||
+ attr.SetFlags(POSIX_SPAWN_CLOEXEC_DEFAULT);
|
||
+
|
||
+ PosixSpawnFileActions file_actions;
|
||
+ for (int fd = 0; fd <= STDERR_FILENO; ++fd) {
|
||
+ file_actions.AddInheritedFileDescriptor(fd);
|
||
+ }
|
||
+ file_actions.AddInheritedFileDescriptor(preserve_fd);
|
||
+
|
||
+ const posix_spawnattr_t* attr_p = attr.Get();
|
||
+ const posix_spawn_file_actions_t* file_actions_p = file_actions.Get();
|
||
+#else
|
||
+ CloseMultipleNowOrOnExec(STDERR_FILENO + 1, preserve_fd);
|
||
+
|
||
+ const posix_spawnattr_t* attr_p = nullptr;
|
||
+ const posix_spawn_file_actions_t* file_actions_p = nullptr;
|
||
+#endif
|
||
+
|
||
+ auto posix_spawn_fp = use_path ? posix_spawnp : posix_spawn;
|
||
+ if ((errno = posix_spawn_fp(&pid,
|
||
+ argv_for_spawn[0],
|
||
+ file_actions_p,
|
||
+ attr_p,
|
||
+ argv_for_spawn,
|
||
+ envp_for_spawn)) != 0) {
|
||
+ PLOG(FATAL) << (use_path ? "posix_spawnp" : "posix_spawn");
|
||
+ }
|
||
+
|
||
+ // _exit() instead of exit(), because fork() was called.
|
||
+ _exit(EXIT_SUCCESS);
|
||
+ }
|
||
+
|
||
+ // waitpid() for the child, so that it does not become a zombie process. The
|
||
+ // child normally exits quickly.
|
||
+ //
|
||
+ // Failures from this point on may result in the accumulation of a zombie, but
|
||
+ // should not be considered fatal. Log only warnings, but don’t treat these
|
||
+ // failures as a failure of the function overall.
|
||
+ int status;
|
||
+ pid_t wait_pid = HANDLE_EINTR(waitpid(pid, &status, 0));
|
||
+ if (wait_pid == -1) {
|
||
+ PLOG(WARNING) << "waitpid";
|
||
+ return true;
|
||
+ }
|
||
+ DCHECK_EQ(wait_pid, pid);
|
||
+
|
||
+ if (WIFSIGNALED(status)) {
|
||
+ int sig = WTERMSIG(status);
|
||
+ LOG(WARNING) << base::StringPrintf(
|
||
+ "intermediate process terminated by signal %d (%s)%s",
|
||
+ sig,
|
||
+ strsignal(sig),
|
||
+ WCOREDUMP(status) ? " (core dumped)" : "");
|
||
+ } else if (!WIFEXITED(status)) {
|
||
+ LOG(WARNING) << base::StringPrintf(
|
||
+ "intermediate process: unknown termination 0x%x", status);
|
||
+ } else if (WEXITSTATUS(status) != EXIT_SUCCESS) {
|
||
+ LOG(WARNING) << "intermediate process exited with code "
|
||
+ << WEXITSTATUS(status);
|
||
+ }
|
||
+
|
||
+ return true;
|
||
+}
|
||
+
|
||
+} // namespace crashpad
|
||
diff --git a/third_party/crashpad/crashpad/util/posix/double_fork_and_exec.h b/third_party/crashpad/crashpad/util/posix/fork_and_spawn.h
|
||
similarity index 76%
|
||
rename from third_party/crashpad/crashpad/util/posix/double_fork_and_exec.h
|
||
rename to third_party/crashpad/crashpad/util/posix/fork_and_spawn.h
|
||
index 02fc0f28f196b447132a2dcfaebdaaa5a916a38a..fc55aa3a37652e4ba18c66db90124abd9cad2e51 100644
|
||
--- a/third_party/crashpad/crashpad/util/posix/double_fork_and_exec.h
|
||
+++ b/third_party/crashpad/crashpad/util/posix/fork_and_spawn.h
|
||
@@ -12,8 +12,8 @@
|
||
// See the License for the specific language governing permissions and
|
||
// limitations under the License.
|
||
|
||
-#ifndef CRASHPAD_UTIL_POSIX_DOUBLE_FORK_AND_EXEC_H_
|
||
-#define CRASHPAD_UTIL_POSIX_DOUBLE_FORK_AND_EXEC_H_
|
||
+#ifndef CRASHPAD_UTIL_POSIX_FORK_AND_SPAWN_H_
|
||
+#define CRASHPAD_UTIL_POSIX_FORK_AND_SPAWN_H_
|
||
|
||
#include <string>
|
||
#include <vector>
|
||
@@ -23,7 +23,7 @@ namespace crashpad {
|
||
//! \brief Executes a (grand-)child process.
|
||
//!
|
||
//! The grandchild process will be started through the
|
||
-//! double-`fork()`-and-`execv()` pattern. This allows the grandchild to fully
|
||
+//! `fork()`-and-`posix_spawn()` pattern. This allows the grandchild to fully
|
||
//! disassociate from the parent. The grandchild will not be a member of the
|
||
//! parent’s process group or session and will not have a controlling terminal,
|
||
//! providing isolation from signals not intended for it. The grandchild’s
|
||
@@ -37,7 +37,7 @@ namespace crashpad {
|
||
//! \param[in] argv The argument vector to start the grandchild process with.
|
||
//! `argv[0]` is used as the path to the executable.
|
||
//! \param[in] envp A vector of environment variables of the form `var=value` to
|
||
-//! be passed to `execve()`. If this value is `nullptr`, the current
|
||
+//! be passed to `posix_spawn()`. If this value is `nullptr`, the current
|
||
//! environment is used.
|
||
//! \param[in] preserve_fd A file descriptor to be inherited by the grandchild
|
||
//! process. This file descriptor is inherited in addition to the three file
|
||
@@ -45,16 +45,13 @@ namespace crashpad {
|
||
//! if no additional file descriptors are to be inherited.
|
||
//! \param[in] use_path Whether to consult the `PATH` environment variable when
|
||
//! requested to start an executable at a non-absolute path. If `false`,
|
||
-//! `execv()`, which does not consult `PATH`, will be used. If `true`,
|
||
-//! `execvp()`, which does consult `PATH`, will be used.
|
||
+//! `posix_spawn()`, which does not consult `PATH`, will be used. If `true`,
|
||
+//! `posix_spawnp()`, which does consult `PATH`, will be used.
|
||
//! \param[in] child_function If not `nullptr`, this function will be called in
|
||
-//! the intermediate child process, prior to the second `fork()`. Take note
|
||
+//! the intermediate child process, prior to the `posix_spawn()`. Take note
|
||
//! that this function will run in the context of a forked process, and must
|
||
//! be safe for that purpose.
|
||
//!
|
||
-//! Setting both \a envp to a value other than `nullptr` and \a use_path to
|
||
-//! `true` is not currently supported.
|
||
-//!
|
||
//! \return `true` on success, and `false` on failure with a message logged.
|
||
//! Only failures that occur in the parent process that indicate a definite
|
||
//! failure to start the the grandchild are reported in the return value.
|
||
@@ -63,12 +60,12 @@ namespace crashpad {
|
||
//! terminating. The caller assumes the responsibility for detecting such
|
||
//! failures, for example, by observing a failure to perform a successful
|
||
//! handshake with the grandchild process.
|
||
-bool DoubleForkAndExec(const std::vector<std::string>& argv,
|
||
- const std::vector<std::string>* envp,
|
||
- int preserve_fd,
|
||
- bool use_path,
|
||
- void (*child_function)());
|
||
+bool ForkAndSpawn(const std::vector<std::string>& argv,
|
||
+ const std::vector<std::string>* envp,
|
||
+ int preserve_fd,
|
||
+ bool use_path,
|
||
+ void (*child_function)());
|
||
|
||
} // namespace crashpad
|
||
|
||
-#endif // CRASHPAD_UTIL_POSIX_DOUBLE_FORK_AND_EXEC_H_
|
||
+#endif // CRASHPAD_UTIL_POSIX_FORK_AND_SPAWN_H_
|