blob: 3e7413648e348b7b20c97dd60ab1233d5cf164b6 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "launch.h"
#include <lib/fdio/spawn.h>
#include <lib/zx/process.h>
#include <lib/zx/time.h>
#include <stdio.h>
#include <unistd.h>
#include <zircon/assert.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>
namespace {
zx::process Launch(const char* const* argv) {
ZX_ASSERT(argv);
fdio_spawn_action_t actions[1] = {{
.action = FDIO_SPAWN_ACTION_SET_NAME,
.name = {.data = "worker"},
}};
char error[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
zx_handle_t subprocess;
zx_status_t status = fdio_spawn_etc(ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL, argv[0], argv, NULL,
1, actions, &subprocess, error);
if (status != ZX_OK) {
printf("Subprocess launch failed: %s\n", error);
subprocess = ZX_HANDLE_INVALID;
}
return zx::process(subprocess);
}
bool WaitForExit(const zx::process& process, int64_t* exit_code) {
zx_signals_t signals_observed = 0;
zx_status_t status =
process.wait_one(ZX_TASK_TERMINATED, zx::time::infinite(), &signals_observed);
if (status != ZX_OK) {
printf("zx_object_wait_one failed, status: %d\n", status);
return false;
}
zx_info_process_t proc_info;
status = process.get_info(ZX_INFO_PROCESS, &proc_info, sizeof(proc_info), nullptr, nullptr);
if (status != ZX_OK) {
printf("zx_object_get_info failed, status: %d\n", status);
return false;
}
*exit_code = proc_info.return_code;
return true;
}
} // namespace.
int Execute(const char** argv) {
zx::process process = Launch(argv);
if (process == ZX_HANDLE_INVALID) {
return -1;
}
int64_t exit_code;
if (!WaitForExit(process, &exit_code)) {
printf("Unable to get return code\n");
return -1;
}
return static_cast<int>(exit_code);
}