Implement DeProcess on fdio_spawn_etc
Launchpad has been replaced.
TEST: vim2:go/magma-tps#C0
Change-Id: Ic8a05b149e2383a3cf83825b3c29dc7c735d937c
diff --git a/framework/delibs/deutil/CMakeLists.txt b/framework/delibs/deutil/CMakeLists.txt
index 2850ed8..53d29af 100644
--- a/framework/delibs/deutil/CMakeLists.txt
+++ b/framework/delibs/deutil/CMakeLists.txt
@@ -21,9 +21,8 @@
if (DE_OS_IS_FUCHSIA)
set(DEUTIL_SRCS ${DEUTIL_SRCS} deFuchsiaProcess.cc)
- include_directories("${FUCHSIA_ROOT}/zircon/system/ulib/launchpad/include")
include_directories("${FUCHSIA_ROOT}/zircon/system/ulib/fdio/include")
- set(DEUTIL_LIBS ${DEUTIL_LIBS} ${FUCHSIA_LIB_DIR}/liblaunchpad.so ${FUCHSIA_LIB_DIR}/libfdio.so zircon)
+ set(DEUTIL_LIBS ${DEUTIL_LIBS} ${FUCHSIA_LIB_DIR}/libfdio.so zircon)
else ()
set(DEUTIL_SRCS ${DEUTIL_SRCS} deProcess.c)
endif ()
diff --git a/framework/delibs/deutil/deCommandLine.c b/framework/delibs/deutil/deCommandLine.c
index d0ebb1c..0c0bf96 100644
--- a/framework/delibs/deutil/deCommandLine.c
+++ b/framework/delibs/deutil/deCommandLine.c
@@ -118,7 +118,7 @@
{
deCommandLine* cmdLine = (deCommandLine*)deCalloc(sizeof(deCommandLine));
- if (!cmdLine || !(cmdLine->args = (char**)deCalloc(sizeof(char*)*(size_t)CharPtrArray_getNumElements(args))))
+ if (!cmdLine || !(cmdLine->args = (char**)deCalloc(sizeof(char*)*(1 + (size_t)CharPtrArray_getNumElements(args)))))
{
deFree(cmdLine);
deFree(buf);
@@ -131,6 +131,7 @@
for (argNdx = 0; argNdx < cmdLine->numArgs; argNdx++)
cmdLine->args[argNdx] = CharPtrArray_get(args, argNdx);
+ cmdLine->args[cmdLine->numArgs] = 0;
deMemPool_destroy(tmpPool);
return cmdLine;
diff --git a/framework/delibs/deutil/deFuchsiaProcess.cc b/framework/delibs/deutil/deFuchsiaProcess.cc
index 0498a87..56508bd 100644
--- a/framework/delibs/deutil/deFuchsiaProcess.cc
+++ b/framework/delibs/deutil/deFuchsiaProcess.cc
@@ -3,17 +3,18 @@
// found in the LICENSE file.
#include <assert.h>
-#include <launchpad/launchpad.h>
-#include <launchpad/vmo.h>
+#include <lib/fdio/io.h>
+#include <lib/fdio/spawn.h>
+#include <lib/fdio/util.h>
+#include <memory.h>
+#include <memory>
+#include <string>
+#include <unistd.h>
+#include <vector>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/object.h>
-#include <memory>
-#include <lib/fdio/io.h>
-#include <lib/fdio/util.h>
-#include <string>
-#include <unistd.h>
#include "deProcess.h"
@@ -26,30 +27,59 @@
struct deProcess_s {
};
+class ModifiedEnviron {
+public:
+ explicit ModifiedEnviron(char** env)
+ {
+ for (size_t i = 0; env[i]; i++) {
+ envs_.push_back(env[i]);
+ }
+ }
+
+ void ReplacePwd(const char* working_directory)
+ {
+ assert(working_directory);
+ char pwd_string[strlen(working_directory) + 4 + 1];
+
+ sprintf(pwd_string, "PWD=%s", working_directory);
+ for (size_t i = 0; i < envs_.size(); i++) {
+ if (strstr(envs_[i].c_str(), "PWD=") == 0) {
+ envs_[i] = pwd_string;
+ return;
+ }
+ }
+ envs_.push_back(pwd_string);
+ }
+
+ // Return value must not outlive ModifiedEnviron. Invalidated if ReplacePwd
+ // is called.
+ std::vector<const char*> GetEnviron()
+ {
+ std::vector<const char*> env;
+ for (size_t i = 0; i < envs_.size(); i++) {
+ env.push_back(envs_[i].c_str());
+ }
+ env.push_back(nullptr);
+ return env;
+ }
+
+private:
+ std::vector<std::string> envs_;
+};
+
class DeProcess : public deProcess_s {
public:
static std::unique_ptr<DeProcess> Create()
{
- zx_handle_t job_copy = ZX_HANDLE_INVALID;
- zx_handle_duplicate(zx_job_default(), ZX_RIGHT_SAME_RIGHTS, &job_copy);
-
- launchpad_t *lp;
- zx_status_t status = launchpad_create(job_copy, "DeProcess", &lp);
- if (status != ZX_OK)
- return std::unique_ptr<DeProcess>();
-
- return std::unique_ptr<DeProcess>(new DeProcess(lp));
+ return std::unique_ptr<DeProcess>(new DeProcess());
}
- DeProcess(launchpad_t* lp)
- : lp_(lp), proc_(ZX_HANDLE_INVALID), fstdin_(nullptr), fstdout_(nullptr), fstderr_(nullptr)
+ DeProcess() : proc_(ZX_HANDLE_INVALID), fstdin_(nullptr), fstdout_(nullptr), fstderr_(nullptr)
{
}
~DeProcess()
{
- if (lp_)
- launchpad_destroy(lp_);
if (proc_ != ZX_HANDLE_INVALID)
zx_handle_close(proc_);
closeStdIn();
@@ -57,32 +87,61 @@
closeStdErr();
}
- launchpad_t* launchpad() { return lp_; }
-
- bool start()
+ bool start(const char* commandLine, const char* workingDirectory)
{
- zx_status_t status;
- status = launchpad_add_pipe(launchpad(), &remote_stdin_fd_, STDIN_FILENO);
- assert(status == ZX_OK);
+ deCommandLine* cmdLine = deCommandLine_parse(commandLine);
+ assert(cmdLine->args[cmdLine->numArgs] == 0);
+ fdio_spawn_action_t spawn_actions[3];
+ int result;
+ int stdin_pipes[2];
+ result = pipe(stdin_pipes);
+ assert(result == 0);
+ int stdout_pipes[2];
+ result = pipe(stdout_pipes);
+ assert(result == 0);
+ int stderr_pipes[2];
+ result = pipe(stderr_pipes);
+ assert(result == 0);
- int stdout_fd;
- status = launchpad_add_pipe(launchpad(), &stdout_fd, STDOUT_FILENO);
- assert(status == ZX_OK);
+ spawn_actions[0].action = FDIO_SPAWN_ACTION_TRANSFER_FD;
+ spawn_actions[0].fd.local_fd = stdin_pipes[0];
+ spawn_actions[0].fd.target_fd = STDIN_FILENO;
+ fstdin_ = deFile_createFromHandle(stdin_pipes[1]);
- int stderr_fd;
- status = launchpad_add_pipe(launchpad(), &stderr_fd, STDERR_FILENO);
- assert(status == ZX_OK);
+ spawn_actions[1].action = FDIO_SPAWN_ACTION_TRANSFER_FD;
+ spawn_actions[1].fd.local_fd = stdout_pipes[1];
+ spawn_actions[1].fd.target_fd = STDOUT_FILENO;
+ fstdout_ = deFile_createFromHandle(stdout_pipes[0]);
- fstdin_ = deFile_createFromHandle(remote_stdin_fd_);
- fstdout_ = deFile_createFromHandle(stdout_fd);
- fstderr_ = deFile_createFromHandle(stderr_fd);
+#ifndef RAW_STDERR
+ spawn_actions[2].action = FDIO_SPAWN_ACTION_TRANSFER_FD;
+ spawn_actions[2].fd.local_fd = stderr_pipes[1];
+ spawn_actions[2].fd.target_fd = STDERR_FILENO;
+ fstderr_ = deFile_createFromHandle(stderr_pipes[0]);
+#else
+ // Printing to our stderr sometimes works better.
+ spawn_actions[2].action = FDIO_SPAWN_ACTION_CLONE_FD;
+ spawn_actions[2].fd.local_fd = STDERR_FILENO;
+ spawn_actions[2].fd.target_fd = STDERR_FILENO;
+ fstderr_ = deFile_createFromHandle(stderr_pipes[0]);
+#endif
- const char* errmsg = NULL;
- status = launchpad_go(lp_, &proc_, &errmsg);
- lp_ = nullptr;
+ ModifiedEnviron env(environ);
+ if (workingDirectory)
+ env.ReplacePwd(workingDirectory);
- if (status != ZX_OK)
+ char err_msg_out[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
+
+ uint32_t spawn_flags = FDIO_SPAWN_CLONE_NAMESPACE | FDIO_SPAWN_CLONE_ENVIRON |
+ FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_JOB;
+ zx_status_t status = fdio_spawn_etc(
+ ZX_HANDLE_INVALID, spawn_flags, cmdLine->args[0], (const char* const*)&cmdLine->args[0],
+ env.GetEnviron().data(), 3, spawn_actions, &proc_, err_msg_out);
+
+ if (status != ZX_OK) {
+ fprintf(stderr, "fdio_spawn error: %d %s\n", status, err_msg_out);
return false;
+ }
return true;
}
@@ -143,9 +202,7 @@
}
private:
- launchpad_t* lp_;
zx_handle_t proc_;
- int remote_stdin_fd_;
deFile* fstdin_;
deFile* fstdout_;
deFile* fstderr_;
@@ -168,26 +225,7 @@
DeProcess* process = DeProcess::cast(de_process);
- deCommandLine* cmdLine = deCommandLine_parse(commandLine);
-
- zx_status_t status;
- status = launchpad_set_args(process->launchpad(), cmdLine->numArgs - 1,
- (const char *const *)&cmdLine->args[1]);
- if (status != ZX_OK)
- fprintf(stderr, "launcpad_set_args failed: %d\n", status);
- assert(status == ZX_OK);
-
- status = launchpad_clone(process->launchpad(), LP_CLONE_FDIO_NAMESPACE | LP_CLONE_ENVIRON);
- assert(status == ZX_OK);
- if (status != ZX_OK)
- fprintf(stderr, "launchpad_clone failed: %d\n", status);
-
- status = launchpad_load_from_file(process->launchpad(), cmdLine->args[0]);
- if (status != ZX_OK)
- fprintf(stderr, "launchpad_load_from_file failed: %d\n", status);
- assert(status == ZX_OK);
-
- if (!process->start())
+ if (!process->start(commandLine, workingDirectory))
return false;
return true;