diff --git a/client/BUILD.gn b/client/BUILD.gn index 662c2441..a074b503 100644 --- a/client/BUILD.gn +++ b/client/BUILD.gn @@ -88,14 +88,10 @@ static_library("client") { cflags = [ "/wd4201" ] # nonstandard extension used : nameless struct/union } - if (crashpad_is_fuchsia) { - if (crashpad_is_in_fuchsia) { - deps += [ - "//zircon/public/lib/launchpad", - ] - } else { - libs = [ "launchpad" ] - } + if (crashpad_is_fuchsia && crashpad_is_in_fuchsia) { + deps += [ + "//zircon/public/lib/fdio", + ] } } diff --git a/client/crashpad_client_fuchsia.cc b/client/crashpad_client_fuchsia.cc index 59cf3873..0d4b8727 100644 --- a/client/crashpad_client_fuchsia.cc +++ b/client/crashpad_client_fuchsia.cc @@ -14,7 +14,7 @@ #include "client/crashpad_client.h" -#include +#include #include #include @@ -69,20 +69,6 @@ bool CrashpadClient::StartHandler( std::vector argv; ConvertArgvStrings(argv_strings, &argv); - // ConvertArgvStrings adds an unnecessary nullptr at the end of the argv list, - // which causes launchpad_set_args() to hang. - argv.pop_back(); - - launchpad_t* lp; - launchpad_create(zx_job_default(), argv[0], &lp); - launchpad_load_from_file(lp, argv[0]); - launchpad_set_args(lp, argv.size(), &argv[0]); - - // TODO(scottmg): https://crashpad.chromium.org/bug/196, this is useful during - // bringup, but should probably be made minimal for real usage. - launchpad_clone(lp, - LP_CLONE_FDIO_NAMESPACE | LP_CLONE_FDIO_STDIO | - LP_CLONE_ENVIRON | LP_CLONE_DEFAULT_JOB); // Follow the same protocol as devmgr and crashlogger in Zircon (that is, // process handle as handle 0, with type USER0, exception port handle as @@ -91,24 +77,39 @@ bool CrashpadClient::StartHandler( // released here. Currently it is assumed that this process's default job // handle is the exception port that should be monitored. In the future, it // might be useful for this to be configurable by the client. - zx_handle_t handles[] = {ZX_HANDLE_INVALID, ZX_HANDLE_INVALID}; - status = - zx_handle_duplicate(zx_job_default(), ZX_RIGHT_SAME_RIGHTS, &handles[0]); + constexpr size_t kActionCount = 2; + fdio_spawn_action_t actions[] = { + {.action = FDIO_SPAWN_ACTION_ADD_HANDLE, + .h = {.id = PA_HND(PA_USER0, 0), .handle = ZX_HANDLE_INVALID}}, + {.action = FDIO_SPAWN_ACTION_ADD_HANDLE, + .h = {.id = PA_HND(PA_USER0, 1), .handle = ZX_HANDLE_INVALID}}, + }; + + status = zx_handle_duplicate( + zx_job_default(), ZX_RIGHT_SAME_RIGHTS, &actions[0].h.handle); if (status != ZX_OK) { ZX_LOG(ERROR, status) << "zx_handle_duplicate"; return false; } - handles[1] = exception_port.release(); - uint32_t handle_types[] = {PA_HND(PA_USER0, 0), PA_HND(PA_USER0, 1)}; + actions[1].h.handle = exception_port.release(); - launchpad_add_handles(lp, arraysize(handles), handles, handle_types); - - const char* error_message; + char error_message[FDIO_SPAWN_ERR_MSG_MAX_LENGTH]; zx_handle_t child_raw; - status = launchpad_go(lp, &child_raw, &error_message); + // TODO(scottmg): https://crashpad.chromium.org/bug/196, FDIO_SPAWN_CLONE_ALL + // is useful during bringup, but should probably be made minimal for real + // usage. + status = fdio_spawn_etc(ZX_HANDLE_INVALID, + FDIO_SPAWN_CLONE_ALL, + argv[0], + argv.data(), + nullptr, + kActionCount, + actions, + &child_raw, + error_message); base::ScopedZxHandle child(child_raw); if (status != ZX_OK) { - ZX_LOG(ERROR, status) << "launchpad_go: " << error_message; + ZX_LOG(ERROR, status) << "fdio_spawn_etc: " << error_message; return false; } diff --git a/test/BUILD.gn b/test/BUILD.gn index ec51e7d2..d1e6297e 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -127,14 +127,10 @@ static_library("test") { libs = [ "shell32.lib" ] } - if (crashpad_is_fuchsia) { - if (crashpad_is_in_fuchsia) { - deps += [ - "//zircon/public/lib/launchpad", - ] - } else { - libs = [ "launchpad" ] - } + if (crashpad_is_fuchsia && crashpad_is_in_fuchsia) { + deps += [ + "//zircon/public/lib/fdio", + ] } } diff --git a/test/multiprocess_exec_fuchsia.cc b/test/multiprocess_exec_fuchsia.cc index 7d571f91..98764222 100644 --- a/test/multiprocess_exec_fuchsia.cc +++ b/test/multiprocess_exec_fuchsia.cc @@ -14,8 +14,10 @@ #include "test/multiprocess_exec.h" -#include +#include +#include #include +#include #include #include "base/files/scoped_file.h" @@ -26,6 +28,21 @@ namespace crashpad { namespace test { +namespace { + +void AddPipe(fdio_spawn_action_t* action, int target_fd, int* fd_out) { + zx_handle_t handle; + uint32_t id; + zx_status_t status = fdio_pipe_half(&handle, &id); + ZX_CHECK(status < 0, status) << "Failed to create pipe."; + action->action = FDIO_SPAWN_ACTION_ADD_HANDLE; + action->h.id = PA_HND(PA_HND_TYPE(id), target_fd); + action->h.handle = handle; + *fd_out = status; +} + +} // namespace + namespace internal { struct MultiprocessInfo { @@ -38,10 +55,7 @@ struct MultiprocessInfo { } // namespace internal Multiprocess::Multiprocess() - : info_(nullptr), - code_(EXIT_SUCCESS), - reason_(kTerminationNormal) { -} + : info_(nullptr), code_(EXIT_SUCCESS), reason_(kTerminationNormal) {} void Multiprocess::Run() { // Set up and spawn the child process. @@ -122,8 +136,7 @@ void Multiprocess::RunChild() { } MultiprocessExec::MultiprocessExec() - : Multiprocess(), command_(), arguments_(), argv_() { -} + : Multiprocess(), command_(), arguments_(), argv_() {} void MultiprocessExec::SetChildCommand( const base::FilePath& command, @@ -147,37 +160,45 @@ void MultiprocessExec::PreFork() { for (const std::string& argument : arguments_) { argv_.push_back(argument.c_str()); } + argv_.push_back(nullptr); 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]); + constexpr size_t kActionCount = 3; + fdio_spawn_action_t actions[kActionCount]; + + int stdin_parent_side = -1; + AddPipe(&actions[0], STDIN_FILENO, &stdin_parent_side); + info()->stdin_write.reset(stdin_parent_side); + + int stdout_parent_side = -1; + AddPipe(&actions[1], STDOUT_FILENO, &stdout_parent_side); + info()->stdout_read.reset(stdout_parent_side); + + actions[2].action = FDIO_SPAWN_ACTION_CLONE_FD; + actions[2].fd.local_fd = STDERR_FILENO; + actions[2].fd.target_fd = STDERR_FILENO; // 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); + uint32_t flags = FDIO_SPAWN_CLONE_ALL & ~FDIO_SPAWN_CLONE_STDIO; - 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; + char error_message[FDIO_SPAWN_ERR_MSG_MAX_LENGTH]; zx_handle_t child; - zx_status_t status = launchpad_go(lp, &child, &error_message); - ZX_CHECK(status == ZX_OK, status) << "launchpad_go: " << error_message; + zx_status_t status = fdio_spawn_etc(ZX_HANDLE_INVALID, + flags, + command_.value().c_str(), + argv_.data(), + nullptr, + kActionCount, + actions, + &child, + error_message); + ZX_CHECK(status == ZX_OK, status) << "fdio_spawn_etc: " << error_message; info()->child.reset(child); } diff --git a/third_party/gtest/BUILD.gn b/third_party/gtest/BUILD.gn index 37fceaf0..6662b6c7 100644 --- a/third_party/gtest/BUILD.gn +++ b/third_party/gtest/BUILD.gn @@ -49,7 +49,6 @@ if (crashpad_is_in_chromium) { if (crashpad_is_fuchsia) { libs = [ - "launchpad", "zircon", ] } @@ -272,7 +271,6 @@ if (crashpad_is_in_chromium) { if (crashpad_is_fuchsia) { libs = [ - "launchpad", "zircon", ] } diff --git a/tools/BUILD.gn b/tools/BUILD.gn index eb76a240..cd1e95f4 100644 --- a/tools/BUILD.gn +++ b/tools/BUILD.gn @@ -104,14 +104,6 @@ if (crashpad_is_mac || crashpad_is_fuchsia) { "../third_party/mini_chromium:base", "../util", ] - - if (crashpad_is_fuchsia) { - if (crashpad_is_in_fuchsia) { - deps += [ "//zircon/public/lib/launchpad" ] - } else { - libs = [ "launchpad" ] - } - } } } diff --git a/tools/run_with_crashpad.cc b/tools/run_with_crashpad.cc index a65f5256..f26dd2bc 100644 --- a/tools/run_with_crashpad.cc +++ b/tools/run_with_crashpad.cc @@ -32,7 +32,7 @@ #include "util/string/split_string.h" #if defined(OS_FUCHSIA) -#include +#include #include #include @@ -48,7 +48,7 @@ void Usage(const std::string& me) { "Start a Crashpad handler and have it handle crashes from COMMAND.\n" "\n" #if defined(OS_FUCHSIA) -"COMMAND is run via launchpad, so must be a qualified path to the subprocess to\n" +"COMMAND is run via fdio_spawn, so must be a qualified path to the subprocess to\n" "be executed.\n" #else "COMMAND is run via execvp() so the PATH will be searched.\n" @@ -190,17 +190,12 @@ int RunWithCrashpadMain(int argc, char* argv[]) { } #if defined(OS_FUCHSIA) - // Fuchsia doesn't implement execvp(), launch with launchpad here. - launchpad_t* lp; - launchpad_create(zx_job_default(), argv[0], &lp); - launchpad_load_from_file(lp, argv[0]); - launchpad_set_args(lp, argc, argv); - launchpad_clone(lp, LP_CLONE_ALL); - const char* error_message; - zx_handle_t child; - zx_status_t status = launchpad_go(lp, &child, &error_message); + // Fuchsia doesn't implement execvp(), launch with fdio_spawn here. + zx_handle_t child = ZX_HANDLE_INVALID; + zx_status_t status = fdio_spawn( + ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL, argv[0], argv, &child); if (status != ZX_OK) { - ZX_LOG(ERROR, status) << "launchpad_go: " << error_message; + ZX_LOG(ERROR, status) << "fdio_spawn failed"; return status == ZX_ERR_IO ? kExitExecENOENT : kExitExecFailure; }