text: // Copyright 2020 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.
  
  // This file has been copied from src/devices/block/drivers/ftl/tests/launch.cc.
  
  #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);
  }
  