mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-26 23:01:05 +08:00
fuchsia: Implementation of MultiprocessExec
This supports multiprocess tests of the non-fork() variety. Also, improve directory finding so that the crashpad_test_test_multiprocess_exec_test_child binary can be located correctly on Fuchsia. Doc ref for launchpad: https://fuchsia.googlesource.com/zircon/+/master/system/ulib/launchpad/include/launchpad/launchpad.h#23 Also, roll mini_chromium to pick up ScopedZxHandle addition. Includes: a19ef08 Merge ScopedZxHandle from Chromium base f21c900 fuchsia: Move zircon libs dep to base, rather than global Bug: crashpad:196 Change-Id: Id01dee43f2d04e682e70c12777aff41f8dd848d6 Reviewed-on: https://chromium-review.googlesource.com/868967 Reviewed-by: Mark Mentovai <mark@chromium.org> Commit-Queue: Scott Graham <scottmg@chromium.org>
This commit is contained in:
parent
380a1e9eaf
commit
f62a30e977
2
DEPS
2
DEPS
@ -28,7 +28,7 @@ deps = {
|
||||
'5e2b3ddde7cda5eb6bc09a5546a76b00e49d888f',
|
||||
'crashpad/third_party/mini_chromium/mini_chromium':
|
||||
Var('chromium_git') + '/chromium/mini_chromium@' +
|
||||
'edfe51ce818e55eae73ab3f144a360e855533888',
|
||||
'a19ef08ada53345fd9277f3d9434bc35f0e13a55',
|
||||
'crashpad/third_party/zlib/zlib':
|
||||
Var('chromium_git') + '/chromium/src/third_party/zlib@' +
|
||||
'13dc246a58e4b72104d35f9b1809af95221ebda7',
|
||||
|
@ -42,13 +42,13 @@ static_library("test") {
|
||||
]
|
||||
|
||||
if (crashpad_is_posix) {
|
||||
sources += [
|
||||
"multiprocess_posix.cc",
|
||||
"scoped_temp_dir_posix.cc",
|
||||
]
|
||||
sources += [ "scoped_temp_dir_posix.cc" ]
|
||||
|
||||
if (!crashpad_is_fuchsia) {
|
||||
sources += [ "multiprocess_exec_posix.cc" ]
|
||||
sources += [
|
||||
"multiprocess_exec_posix.cc",
|
||||
"multiprocess_posix.cc",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,6 +91,11 @@ static_library("test") {
|
||||
]
|
||||
}
|
||||
|
||||
if (crashpad_is_fuchsia) {
|
||||
sources += [ "multiprocess_exec_fuchsia.cc" ]
|
||||
libs = [ "launchpad" ]
|
||||
}
|
||||
|
||||
public_configs = [ "..:crashpad_config" ]
|
||||
|
||||
configs += [ "../build:crashpad_is_in_chromium" ]
|
||||
@ -121,6 +126,7 @@ source_set("test_test") {
|
||||
sources = [
|
||||
"hex_string_test.cc",
|
||||
"main_arguments_test.cc",
|
||||
"multiprocess_exec_test.cc",
|
||||
"scoped_temp_dir_test.cc",
|
||||
"test_paths_test.cc",
|
||||
]
|
||||
@ -141,11 +147,6 @@ source_set("test_test") {
|
||||
}
|
||||
|
||||
if (!crashpad_is_fuchsia) {
|
||||
sources += [
|
||||
# TODO(scottmg): A MultiprocessExecFuchsia is probably desirable, but
|
||||
# hasn't been implemented yet.
|
||||
"multiprocess_exec_test.cc",
|
||||
]
|
||||
}
|
||||
|
||||
deps = [
|
||||
|
@ -36,8 +36,8 @@ struct MultiprocessInfo;
|
||||
//! Subclasses are expected to implement the parent and child by overriding the
|
||||
//! appropriate methods.
|
||||
//!
|
||||
//! On Windows, this class is only an internal implementation detail of
|
||||
//! MultiprocessExec and all tests must use that class.
|
||||
//! On Windows and Fuchsia, this class is only an internal implementation
|
||||
//! detail of MultiprocessExec and all tests must use that class.
|
||||
class Multiprocess {
|
||||
public:
|
||||
//! \brief The termination type for a child process.
|
||||
@ -110,14 +110,18 @@ class Multiprocess {
|
||||
//!
|
||||
//! Subclass implementations may signal failure by raising their own fatal
|
||||
//! gtest assertions.
|
||||
virtual void PreFork();
|
||||
virtual void PreFork()
|
||||
#if defined(OS_WIN) || defined(OS_FUCHSIA)
|
||||
= 0
|
||||
#endif // OS_WIN || OS_FUCHSIA
|
||||
;
|
||||
|
||||
#if !defined(OS_WIN)
|
||||
#if !defined(OS_WIN) && !defined(OS_FUCHSIA)
|
||||
//! \brief Returns the child process’ process ID.
|
||||
//!
|
||||
//! This method may only be called by the parent process.
|
||||
pid_t ChildPID() const;
|
||||
#endif // !OS_WIN
|
||||
#endif // !OS_WIN && !OS_FUCHSIA
|
||||
|
||||
//! \brief Returns the read pipe’s file handle.
|
||||
//!
|
||||
|
155
test/multiprocess_exec_fuchsia.cc
Normal file
155
test/multiprocess_exec_fuchsia.cc
Normal file
@ -0,0 +1,155 @@
|
||||
// Copyright 2018 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 "test/multiprocess_exec.h"
|
||||
|
||||
#include <launchpad/launchpad.h>
|
||||
#include <zircon/process.h>
|
||||
#include <zircon/syscalls.h>
|
||||
|
||||
#include "base/files/scoped_file.h"
|
||||
#include "base/fuchsia/fuchsia_logging.h"
|
||||
#include "base/fuchsia/scoped_zx_handle.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
|
||||
namespace internal {
|
||||
|
||||
struct MultiprocessInfo {
|
||||
MultiprocessInfo() {}
|
||||
base::ScopedFD stdin_write;
|
||||
base::ScopedFD stdout_read;
|
||||
base::ScopedZxHandle child;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
Multiprocess::Multiprocess()
|
||||
: info_(nullptr),
|
||||
code_(EXIT_SUCCESS),
|
||||
reason_(kTerminationNormal) {
|
||||
}
|
||||
|
||||
void Multiprocess::Run() {
|
||||
// Set up and spawn the child process.
|
||||
ASSERT_NO_FATAL_FAILURE(PreFork());
|
||||
RunChild();
|
||||
|
||||
// And then run the parent actions in this process.
|
||||
RunParent();
|
||||
|
||||
// Reap the child.
|
||||
zx_signals_t signals;
|
||||
ASSERT_EQ(
|
||||
zx_object_wait_one(
|
||||
info_->child.get(), ZX_TASK_TERMINATED, ZX_TIME_INFINITE, &signals),
|
||||
ZX_OK);
|
||||
ASSERT_EQ(signals, ZX_TASK_TERMINATED);
|
||||
}
|
||||
|
||||
Multiprocess::~Multiprocess() {
|
||||
delete info_;
|
||||
}
|
||||
|
||||
FileHandle Multiprocess::ReadPipeHandle() const {
|
||||
return info_->stdout_read.get();
|
||||
}
|
||||
|
||||
FileHandle Multiprocess::WritePipeHandle() const {
|
||||
return info_->stdin_write.get();
|
||||
}
|
||||
|
||||
void Multiprocess::CloseReadPipe() {
|
||||
info_->stdout_read.reset();
|
||||
}
|
||||
|
||||
void Multiprocess::CloseWritePipe() {
|
||||
info_->stdin_write.reset();
|
||||
}
|
||||
|
||||
void Multiprocess::RunParent() {
|
||||
MultiprocessParent();
|
||||
|
||||
info_->stdout_read.reset();
|
||||
info_->stdin_write.reset();
|
||||
}
|
||||
|
||||
void Multiprocess::RunChild() {
|
||||
MultiprocessChild();
|
||||
}
|
||||
|
||||
MultiprocessExec::MultiprocessExec()
|
||||
: Multiprocess(), command_(), arguments_(), argv_() {
|
||||
}
|
||||
|
||||
void MultiprocessExec::SetChildCommand(
|
||||
const base::FilePath& command,
|
||||
const std::vector<std::string>* arguments) {
|
||||
command_ = command;
|
||||
if (arguments) {
|
||||
arguments_ = *arguments;
|
||||
} else {
|
||||
arguments_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
MultiprocessExec::~MultiprocessExec() {}
|
||||
|
||||
void MultiprocessExec::PreFork() {
|
||||
ASSERT_FALSE(command_.empty());
|
||||
|
||||
ASSERT_TRUE(argv_.empty());
|
||||
|
||||
argv_.push_back(command_.value().c_str());
|
||||
for (const std::string& argument : arguments_) {
|
||||
argv_.push_back(argument.c_str());
|
||||
}
|
||||
|
||||
ASSERT_EQ(info(), nullptr);
|
||||
set_info(new internal::MultiprocessInfo());
|
||||
}
|
||||
|
||||
void MultiprocessExec::MultiprocessChild() {
|
||||
launchpad_t* lp;
|
||||
launchpad_create(zx_job_default(), command_.value().c_str(), &lp);
|
||||
launchpad_load_from_file(lp, command_.value().c_str());
|
||||
launchpad_set_args(lp, argv_.size(), &argv_[0]);
|
||||
|
||||
// Pass the filesystem namespace, parent environment, and default job to the
|
||||
// child, but don't include any other file handles, preferring to set them
|
||||
// up explicitly below.
|
||||
launchpad_clone(
|
||||
lp, LP_CLONE_FDIO_NAMESPACE | LP_CLONE_ENVIRON | LP_CLONE_DEFAULT_JOB);
|
||||
|
||||
int stdin_parent_side;
|
||||
launchpad_add_pipe(lp, &stdin_parent_side, STDIN_FILENO);
|
||||
info()->stdin_write.reset(stdin_parent_side);
|
||||
|
||||
int stdout_parent_side;
|
||||
launchpad_add_pipe(lp, &stdout_parent_side, STDOUT_FILENO);
|
||||
info()->stdout_read.reset(stdout_parent_side);
|
||||
|
||||
launchpad_clone_fd(lp, STDERR_FILENO, STDERR_FILENO);
|
||||
|
||||
const char* error_message;
|
||||
zx_handle_t child;
|
||||
zx_status_t status = launchpad_go(lp, &child, &error_message);
|
||||
ZX_CHECK(status == ZX_OK, status) << "launchpad_go: " << error_message;
|
||||
info()->child.reset(child);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
@ -61,10 +61,6 @@ Multiprocess::~Multiprocess() {
|
||||
delete info_;
|
||||
}
|
||||
|
||||
void Multiprocess::PreFork() {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
FileHandle Multiprocess::ReadPipeHandle() const {
|
||||
// This is the parent case, it's stdin in the child.
|
||||
return info_->pipe_c2p_read.get();
|
||||
|
@ -170,7 +170,7 @@ base::FilePath TestPaths::BuildArtifact(
|
||||
|
||||
base::FilePath::StringType test_name =
|
||||
FILE_PATH_LITERAL("crashpad_") + module + FILE_PATH_LITERAL("_test");
|
||||
#if !defined(CRASHPAD_IS_IN_CHROMIUM)
|
||||
#if !defined(CRASHPAD_IS_IN_CHROMIUM) && !defined(OS_FUCHSIA)
|
||||
CHECK(Executable().BaseName().RemoveFinalExtension().value() == test_name);
|
||||
#endif // !CRASHPAD_IS_IN_CHROMIUM
|
||||
|
||||
@ -182,6 +182,8 @@ base::FilePath TestPaths::BuildArtifact(
|
||||
case FileType::kExecutable:
|
||||
#if defined(OS_WIN)
|
||||
extension = FILE_PATH_LITERAL(".exe");
|
||||
#elif defined(OS_FUCHSIA)
|
||||
directory = base::FilePath(FILE_PATH_LITERAL("/pkg/bin"));
|
||||
#endif // OS_WIN
|
||||
break;
|
||||
|
||||
@ -191,6 +193,10 @@ base::FilePath TestPaths::BuildArtifact(
|
||||
#else // OS_WIN
|
||||
extension = FILE_PATH_LITERAL(".so");
|
||||
#endif // OS_WIN
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
directory = base::FilePath(FILE_PATH_LITERAL("/pkg/lib"));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -26,9 +26,8 @@ namespace crashpad {
|
||||
bool Paths::Executable(base::FilePath* path) {
|
||||
// Assume the environment has been set up following
|
||||
// https://fuchsia.googlesource.com/docs/+/master/namespaces.md#typical-directory-structure
|
||||
// . The actual executable name is not known, but it's conceptually in this
|
||||
// location.
|
||||
*path = base::FilePath("/pkg/bin/unknown");
|
||||
// .
|
||||
*path = base::FilePath("/pkg/bin/app");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user