Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(567)

Unified Diff: runtime/bin/process_fuchsia.cc

Issue 2563463002: Fuchsia: dart:io Processes (Closed)
Patch Set: Format Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/bin/fdutils_fuchsia.cc ('k') | runtime/bin/socket_fuchsia.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/process_fuchsia.cc
diff --git a/runtime/bin/process_fuchsia.cc b/runtime/bin/process_fuchsia.cc
index 058234f752229bcf5d988ced5e85527cbca00583..2bcef56c3a7f91cf1ac143240db8a4a5f8eb97d3 100644
--- a/runtime/bin/process_fuchsia.cc
+++ b/runtime/bin/process_fuchsia.cc
@@ -9,9 +9,35 @@
#include "bin/process.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <launchpad/launchpad.h>
+#include <launchpad/vmo.h>
+#include <magenta/status.h>
+#include <magenta/syscalls.h>
+#include <magenta/syscalls/object.h>
+#include <mxio/util.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "bin/dartutils.h"
+#include "bin/fdutils.h"
#include "bin/lockers.h"
-#include "platform/assert.h"
+#include "bin/log.h"
+#include "platform/signal_blocker.h"
+// #define PROCESS_LOGGING 1
+#if defined(PROCESS_LOGGING)
+#define LOG_ERR(msg, ...) Log::PrintErr("Dart Process: " msg, ##__VA_ARGS__)
+#define LOG_INFO(msg, ...) Log::Print("Dart Process: " msg, ##__VA_ARGS__)
+#else
+#define LOG_ERR(msg, ...)
+#define LOG_INFO(msg, ...)
+#endif // defined(PROCESS_LOGGING)
namespace dart {
namespace bin {
@@ -20,23 +46,385 @@ int Process::global_exit_code_ = 0;
Mutex* Process::global_exit_code_mutex_ = new Mutex();
Process::ExitHook Process::exit_hook_ = NULL;
-void Process::TerminateExitCodeHandler() {}
+// ProcessInfo is used to map a process id to the file descriptor for
+// the pipe used to communicate the exit code of the process to Dart.
+// ProcessInfo objects are kept in the static singly-linked
+// ProcessInfoList.
+class ProcessInfo {
+ public:
+ ProcessInfo(mx_handle_t process, intptr_t fd)
+ : process_(process), exit_pipe_fd_(fd) {}
+ ~ProcessInfo() {
+ int closed = NO_RETRY_EXPECTED(close(exit_pipe_fd_));
+ if (closed != 0) {
+ FATAL("Failed to close process exit code pipe");
+ }
+ }
+ mx_handle_t process() const { return process_; }
+ intptr_t exit_pipe_fd() const { return exit_pipe_fd_; }
+ ProcessInfo* next() const { return next_; }
+ void set_next(ProcessInfo* info) { next_ = info; }
-intptr_t Process::CurrentProcessId() {
- UNIMPLEMENTED();
- return 0;
-}
+ private:
+ mx_handle_t process_;
+ intptr_t exit_pipe_fd_;
+ ProcessInfo* next_;
-intptr_t Process::SetSignalHandler(intptr_t signal) {
- UNIMPLEMENTED();
- return -1;
+ DISALLOW_COPY_AND_ASSIGN(ProcessInfo);
+};
+
+
+// Singly-linked list of ProcessInfo objects for all active processes
+// started from Dart.
+class ProcessInfoList {
+ public:
+ static void AddProcess(mx_handle_t process, intptr_t fd) {
+ MutexLocker locker(mutex_);
+ ProcessInfo* info = new ProcessInfo(process, fd);
+ info->set_next(active_processes_);
+ active_processes_ = info;
+ }
+
+
+ static intptr_t LookupProcessExitFd(mx_handle_t process) {
+ MutexLocker locker(mutex_);
+ ProcessInfo* current = active_processes_;
+ while (current != NULL) {
+ if (current->process() == process) {
+ return current->exit_pipe_fd();
+ }
+ current = current->next();
+ }
+ return 0;
+ }
+
+
+ static void RemoveProcess(mx_handle_t process) {
+ MutexLocker locker(mutex_);
+ ProcessInfo* prev = NULL;
+ ProcessInfo* current = active_processes_;
+ while (current != NULL) {
+ if (current->process() == process) {
+ if (prev == NULL) {
+ active_processes_ = current->next();
+ } else {
+ prev->set_next(current->next());
+ }
+ delete current;
+ return;
+ }
+ prev = current;
+ current = current->next();
+ }
+ }
+
+ private:
+ // Linked list of ProcessInfo objects for all active processes
+ // started from Dart code.
+ static ProcessInfo* active_processes_;
+ // Mutex protecting all accesses to the linked list of active
+ // processes.
+ static Mutex* mutex_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList);
+};
+
+ProcessInfo* ProcessInfoList::active_processes_ = NULL;
+Mutex* ProcessInfoList::mutex_ = new Mutex();
+
+// The exit code handler sets up a separate thread which waits for child
+// processes to terminate. That separate thread can then get the exit code from
+// processes that have exited and communicate it to Dart through the
+// event loop.
+class ExitCodeHandler {
+ public:
+ // Notify the ExitCodeHandler that another process exists.
+ static void Start() {
+ // Multiple isolates could be starting processes at the same
+ // time. Make sure that only one ExitCodeHandler thread exists.
+ MonitorLocker locker(monitor_);
+ if (running_) {
+ return;
+ }
+
+ LOG_INFO("ExitCodeHandler Starting\n");
+
+ mx_status_t status = mx_socket_create(0, &interrupt_in_, &interrupt_out_);
+ if (status < 0) {
+ FATAL1("Failed to create exit code handler interrupt socket: %s\n",
+ mx_status_get_string(status));
+ }
+
+ // Start thread that handles process exits when wait returns.
+ intptr_t result =
+ Thread::Start(ExitCodeHandlerEntry, static_cast<uword>(interrupt_out_));
+ if (result != 0) {
+ FATAL1("Failed to start exit code handler worker thread %ld", result);
+ }
+
+ running_ = true;
+ }
+
+ static void Add(mx_handle_t process) {
+ MonitorLocker locker(monitor_);
+ LOG_INFO("ExitCodeHandler Adding Process: %ld\n", process);
+ SendMessage(Message::kAdd, process);
+ }
+
+ static void Terminate() {
+ MonitorLocker locker(monitor_);
+ if (!running_) {
+ return;
+ }
+ running_ = false;
+
+ LOG_INFO("ExitCodeHandler Terminating\n");
+ SendMessage(Message::kShutdown, MX_HANDLE_INVALID);
+
+ while (!terminate_done_) {
+ monitor_->Wait(Monitor::kNoTimeout);
+ }
+ mx_handle_close(interrupt_in_);
+ LOG_INFO("ExitCodeHandler Terminated\n");
+ }
+
+ private:
+ class Message {
+ public:
+ enum Command {
+ kAdd,
+ kShutdown,
+ };
+ Command command;
+ mx_handle_t handle;
+ };
+
+ static void SendMessage(Message::Command command, mx_handle_t handle) {
+ Message msg;
+ msg.command = command;
+ msg.handle = handle;
+ size_t actual;
+ mx_status_t status =
+ mx_socket_write(interrupt_in_, 0, &msg, sizeof(msg), &actual);
+ if (status < 0) {
+ FATAL1("Write to exit handler interrupt handle failed: %s\n",
+ mx_status_get_string(status));
+ }
+ ASSERT(actual == sizeof(msg));
+ }
+
+ // Entry point for the separate exit code handler thread started by
+ // the ExitCodeHandler.
+ static void ExitCodeHandlerEntry(uword param) {
+ LOG_INFO("ExitCodeHandler Entering ExitCodeHandler thread\n");
+ item_capacity_ = 16;
+ items_ = reinterpret_cast<mx_wait_item_t*>(
+ malloc(item_capacity_ * sizeof(*items_)));
+ items_to_remove_ = reinterpret_cast<intptr_t*>(
+ malloc(item_capacity_ * sizeof(*items_to_remove_)));
+
+ // The interrupt handle is fixed to the first entry.
+ items_[0].handle = interrupt_out_;
+ items_[0].waitfor = MX_SOCKET_READABLE | MX_SOCKET_PEER_CLOSED;
+ items_[0].pending = MX_SIGNAL_NONE;
+ item_count_ = 1;
+
+ while (!do_shutdown_) {
+ LOG_INFO("ExitCodeHandler Calling mx_handle_wait_many: %ld items\n",
+ item_count_);
+ mx_status_t status =
+ mx_handle_wait_many(items_, item_count_, MX_TIME_INFINITE);
+ if (status < 0) {
+ FATAL1("Exit code handler handle wait failed: %s\n",
+ mx_status_get_string(status));
+ }
+ LOG_INFO("ExitCodeHandler mx_handle_wait_many returned\n");
+
+ bool have_interrupt = false;
+ intptr_t remove_count = 0;
+ for (intptr_t i = 0; i < item_count_; i++) {
+ if (items_[i].pending == MX_SIGNAL_NONE) {
+ continue;
+ }
+ if (i == 0) {
+ LOG_INFO("ExitCodeHandler thread saw interrupt\n");
+ have_interrupt = true;
+ continue;
+ }
+ ASSERT(items_[i].waitfor == MX_TASK_TERMINATED);
+ ASSERT((items_[i].pending & MX_TASK_TERMINATED) != 0);
+ LOG_INFO("ExitCodeHandler signal for %ld\n", items_[i].handle);
+ SendProcessStatus(items_[i].handle);
+ items_to_remove_[remove_count++] = i;
+ }
+ for (intptr_t i = 0; i < remove_count; i++) {
+ RemoveItem(items_to_remove_[i]);
+ }
+ if (have_interrupt) {
+ HandleInterruptMsg();
+ }
+ }
+
+ LOG_INFO("ExitCodeHandler thread shutting down\n");
+ mx_handle_close(interrupt_out_);
+ free(items_);
+ items_ = NULL;
+ free(items_to_remove_);
+ items_to_remove_ = NULL;
+ item_count_ = 0;
+ item_capacity_ = 0;
+
+ terminate_done_ = true;
+ monitor_->Notify();
+ }
+
+ static void SendProcessStatus(mx_handle_t process) {
+ LOG_INFO("ExitCodeHandler thread getting process status: %ld\n", process);
+ mx_info_process_t proc_info;
+ mx_status_t status = mx_object_get_info(
+ process, MX_INFO_PROCESS, &proc_info, sizeof(proc_info), NULL, NULL);
+ if (status < 0) {
+ FATAL1("mx_object_get_info failed on process handle: %s\n",
+ mx_status_get_string(status));
+ }
+
+ const int return_code = proc_info.return_code;
+ status = mx_handle_close(process);
+ if (status < 0) {
+ FATAL1("Failed to close process handle: %s\n",
+ mx_status_get_string(status));
+ }
+ LOG_INFO("ExitCodeHandler thread process %ld exited with %d\n", process,
+ return_code);
+
+ const intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(process);
+ LOG_INFO("ExitCodeHandler thread sending %ld code %d on fd %ld\n", process,
+ return_code, exit_code_fd);
+ if (exit_code_fd != 0) {
+ int exit_message[2];
+ exit_message[0] = return_code;
+ exit_message[1] = 0; // Do not negate return_code.
+ intptr_t result = FDUtils::WriteToBlocking(exit_code_fd, &exit_message,
+ sizeof(exit_message));
+ ASSERT((result == -1) || (result == sizeof(exit_code_fd)));
+ if ((result == -1) && (errno != EPIPE)) {
+ int err = errno;
+ FATAL1("Failed to write exit code to pipe: %d\n", err);
+ }
+ LOG_INFO("ExitCodeHandler thread wrote %ld bytes to fd %ld\n", result,
+ exit_code_fd);
+ LOG_INFO("ExitCodeHandler thread removing process %ld from list\n",
+ process);
+ ProcessInfoList::RemoveProcess(process);
+ }
+ }
+
+ static void HandleInterruptMsg() {
+ ASSERT(items_[0].handle == interrupt_out_);
+ ASSERT(items_[0].waitfor == MX_SOCKET_READABLE);
+ ASSERT((items_[0].pending & MX_SOCKET_READABLE) != 0);
+ while (true) {
+ Message msg;
+ size_t actual = 0;
+ LOG_INFO("ExitCodeHandler thread reading interrupt message\n");
+ mx_status_t status =
+ mx_socket_read(interrupt_out_, 0, &msg, sizeof(msg), &actual);
+ if (status == ERR_SHOULD_WAIT) {
+ LOG_INFO("ExitCodeHandler thread done reading interrupt messages\n");
+ return;
+ }
+ if (status < 0) {
+ FATAL1("Failed to read exit handler interrupt handle: %s\n",
+ mx_status_get_string(status));
+ }
+ if (actual < sizeof(msg)) {
+ FATAL1("Short read from exit handler interrupt handle: %ld\n", actual);
+ }
+ switch (msg.command) {
+ case Message::kShutdown:
+ LOG_INFO("ExitCodeHandler thread got shutdown message\n");
+ do_shutdown_ = true;
+ break;
+ case Message::kAdd:
+ LOG_INFO("ExitCodeHandler thread got add message: %ld\n", msg.handle);
+ AddItem(msg.handle);
+ break;
+ }
+ }
+ }
+
+ static void AddItem(mx_handle_t h) {
+ if (item_count_ == item_capacity_) {
+ item_capacity_ = item_capacity_ + (item_capacity_ >> 1);
+ items_ =
+ reinterpret_cast<mx_wait_item_t*>(realloc(items_, item_capacity_));
+ items_to_remove_ = reinterpret_cast<intptr_t*>(
+ realloc(items_to_remove_, item_capacity_));
+ }
+ LOG_INFO("ExitCodeHandler thread adding item %ld at %ld\n", h, item_count_);
+ items_[item_count_].handle = h;
+ items_[item_count_].waitfor = MX_TASK_TERMINATED;
+ items_[item_count_].pending = MX_SIGNAL_NONE;
+ item_count_++;
+ }
+
+ static void RemoveItem(intptr_t idx) {
+ LOG_INFO("ExitCodeHandler thread removing item %ld at %ld\n",
+ items_[idx].handle, idx);
+ ASSERT(idx != 0);
+ const intptr_t last = item_count_ - 1;
+ items_[idx].handle = MX_HANDLE_INVALID;
+ items_[idx].waitfor = MX_SIGNAL_NONE;
+ items_[idx].pending = MX_SIGNAL_NONE;
+ if (idx != last) {
+ items_[idx] = items_[last];
+ }
+ item_count_--;
+ }
+
+ // Interrupt message pipe.
+ static mx_handle_t interrupt_in_;
+ static mx_handle_t interrupt_out_;
+
+ // Accessed only by the ExitCodeHandler thread.
+ static mx_wait_item_t* items_;
+ static intptr_t* items_to_remove_;
+ static intptr_t item_count_;
+ static intptr_t item_capacity_;
+
+ // Protected by monitor_.
+ static bool do_shutdown_;
+ static bool terminate_done_;
+ static bool running_;
+ static Monitor* monitor_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler);
+};
+
+mx_handle_t ExitCodeHandler::interrupt_in_ = MX_HANDLE_INVALID;
+mx_handle_t ExitCodeHandler::interrupt_out_ = MX_HANDLE_INVALID;
+mx_wait_item_t* ExitCodeHandler::items_ = NULL;
+intptr_t* ExitCodeHandler::items_to_remove_ = NULL;
+intptr_t ExitCodeHandler::item_count_ = 0;
+intptr_t ExitCodeHandler::item_capacity_ = 0;
+
+bool ExitCodeHandler::do_shutdown_ = false;
+bool ExitCodeHandler::running_ = false;
+bool ExitCodeHandler::terminate_done_ = false;
+Monitor* ExitCodeHandler::monitor_ = new Monitor();
+
+void Process::TerminateExitCodeHandler() {
+ ExitCodeHandler::Terminate();
}
-void Process::ClearSignalHandler(intptr_t signal) {
- UNIMPLEMENTED();
+intptr_t Process::CurrentProcessId() {
+ return static_cast<intptr_t>(getpid());
}
+
bool Process::Wait(intptr_t pid,
intptr_t in,
intptr_t out,
@@ -47,11 +435,230 @@ bool Process::Wait(intptr_t pid,
return false;
}
+
bool Process::Kill(intptr_t id, int signal) {
UNIMPLEMENTED();
return false;
}
+
+class ProcessStarter {
+ public:
+ ProcessStarter(const char* path,
+ char* arguments[],
+ intptr_t arguments_length,
+ const char* working_directory,
+ char* environment[],
+ intptr_t environment_length,
+ ProcessStartMode mode,
+ intptr_t* in,
+ intptr_t* out,
+ intptr_t* err,
+ intptr_t* id,
+ intptr_t* exit_event,
+ char** os_error_message)
+ : path_(path),
+ working_directory_(working_directory),
+ mode_(mode),
+ in_(in),
+ out_(out),
+ err_(err),
+ id_(id),
+ exit_event_(exit_event),
+ os_error_message_(os_error_message) {
+ LOG_INFO("ProcessStarter: ctor %s with %ld args, mode = %d\n", path,
+ arguments_length, mode);
+
+ read_in_ = -1;
+ read_err_ = -1;
+ write_out_ = -1;
+
+ program_arguments_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
+ (arguments_length + 2) * sizeof(*program_arguments_)));
+ program_arguments_[0] = const_cast<char*>(path_);
+ for (int i = 0; i < arguments_length; i++) {
+ program_arguments_[i + 1] = arguments[i];
+ }
+ program_arguments_[arguments_length + 1] = NULL;
+ program_arguments_count_ = arguments_length + 1;
+
+ program_environment_ = NULL;
+ if (environment != NULL) {
+ program_environment_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
+ (environment_length + 1) * sizeof(*program_environment_)));
+ for (int i = 0; i < environment_length; i++) {
+ program_environment_[i] = environment[i];
+ }
+ program_environment_[environment_length] = NULL;
+ }
+
+ binary_vmo_ = MX_HANDLE_INVALID;
+ launchpad_ = NULL;
+ }
+
+ ~ProcessStarter() {
+ if (binary_vmo_ != MX_HANDLE_INVALID) {
+ mx_handle_close(binary_vmo_);
+ }
+ if (launchpad_ != NULL) {
+ launchpad_destroy(launchpad_);
+ }
+ if (read_in_ != -1) {
+ close(read_in_);
+ }
+ if (read_err_ != -1) {
+ close(read_err_);
+ }
+ if (write_out_ != -1) {
+ close(write_out_);
+ }
+ }
+
+ int Start() {
+ LOG_INFO("ProcessStarter: Start()\n");
+ int exit_pipe_fds[2];
+ intptr_t result = NO_RETRY_EXPECTED(pipe(exit_pipe_fds));
+ if (result != 0) {
+ *os_error_message_ = DartUtils::ScopedCopyCString(
+ "Failed to create exit code pipe for process start.");
+ return result;
+ }
+ LOG_INFO("ProcessStarter: Start() set up exit_pipe_fds (%d, %d)\n",
+ exit_pipe_fds[0], exit_pipe_fds[1]);
+
+ mx_status_t status = SetupLaunchpad();
+ if (status != NO_ERROR) {
+ close(exit_pipe_fds[0]);
+ close(exit_pipe_fds[1]);
+ return status;
+ }
+
+ LOG_INFO("ProcessStarter: Start() Calling launchpad_start\n");
+ mx_handle_t process = launchpad_start(launchpad_);
+ launchpad_destroy(launchpad_);
+ launchpad_ = NULL;
+ if (process < 0) {
+ LOG_INFO("ProcessStarter: Start() launchpad_start failed\n");
+ const intptr_t kMaxMessageSize = 256;
+ close(exit_pipe_fds[0]);
+ close(exit_pipe_fds[1]);
+ char* message = DartUtils::ScopedCString(kMaxMessageSize);
+ snprintf(message, kMaxMessageSize, "%s:%d: launchpad_start failed: %s\n",
+ __FILE__, __LINE__, mx_status_get_string(process));
+ *os_error_message_ = message;
+ return process;
+ }
+
+ LOG_INFO("ProcessStarter: Start() adding %ld to list with exit_pipe %d\n",
+ process, exit_pipe_fds[1]);
+ ProcessInfoList::AddProcess(process, exit_pipe_fds[1]);
+ ExitCodeHandler::Start();
+ ExitCodeHandler::Add(process);
+
+ *id_ = process;
+ FDUtils::SetNonBlocking(read_in_);
+ *in_ = read_in_;
+ read_in_ = -1;
+ FDUtils::SetNonBlocking(read_err_);
+ *err_ = read_err_;
+ read_err_ = -1;
+ FDUtils::SetNonBlocking(write_out_);
+ *out_ = write_out_;
+ write_out_ = -1;
+ FDUtils::SetNonBlocking(exit_pipe_fds[0]);
+ *exit_event_ = exit_pipe_fds[0];
+ return 0;
+ }
+
+ private:
+#define CHECK_FOR_ERROR(status, msg) \
+ if (status < 0) { \
+ const intptr_t kMaxMessageSize = 256; \
+ char* message = DartUtils::ScopedCString(kMaxMessageSize); \
+ snprintf(message, kMaxMessageSize, "%s:%d: %s: %s\n", __FILE__, __LINE__, \
+ msg, mx_status_get_string(status)); \
+ *os_error_message_ = message; \
+ return status; \
+ }
+
+ mx_status_t SetupLaunchpad() {
+ mx_handle_t binary_vmo = launchpad_vmo_from_file(path_);
+ CHECK_FOR_ERROR(binary_vmo, "launchpad_vmo_from_file");
+ binary_vmo_ = binary_vmo;
+
+ launchpad_t* lp;
+ mx_status_t status;
+
+ status = launchpad_create(0, program_arguments_[0], &lp);
+ CHECK_FOR_ERROR(status, "launchpad_create");
+ launchpad_ = lp;
+
+ status =
+ launchpad_arguments(lp, program_arguments_count_, program_arguments_);
+ CHECK_FOR_ERROR(status, "launchpad_arguments");
+
+ status = launchpad_environ(lp, program_environment_);
+ CHECK_FOR_ERROR(status, "launchpad_environ");
+
+ // TODO(zra): Use the supplied working directory when launchpad adds an
+ // API to set it.
+
+ status = launchpad_clone_mxio_root(lp);
+ CHECK_FOR_ERROR(status, "launchpad_clone_mxio_root");
+
+ status = launchpad_add_pipe(lp, &write_out_, 0);
+ CHECK_FOR_ERROR(status, "launchpad_add_pipe");
+
+ status = launchpad_add_pipe(lp, &read_in_, 1);
+ CHECK_FOR_ERROR(status, "launchpad_add_pipe");
+
+ status = launchpad_add_pipe(lp, &read_err_, 2);
+ CHECK_FOR_ERROR(status, "launchpad_add_pipe");
+
+ status = launchpad_add_vdso_vmo(lp);
+ CHECK_FOR_ERROR(status, "launchpad_add_vdso_vmo");
+
+ status = launchpad_elf_load(lp, binary_vmo);
+ CHECK_FOR_ERROR(status, "launchpad_elf_load");
+ binary_vmo_ = MX_HANDLE_INVALID; // launchpad_elf_load consumes the handle.
+
+ status = launchpad_load_vdso(lp, MX_HANDLE_INVALID);
+ CHECK_FOR_ERROR(status, "launchpad_load_vdso");
+
+ status = launchpad_clone_mxio_cwd(lp);
+ CHECK_FOR_ERROR(status, "launchpad_clone_mxio_cwd");
+
+ return NO_ERROR;
+ }
+
+#undef CHECK_FOR_ERROR
+
+ int read_in_; // Pipe for stdout to child process.
+ int read_err_; // Pipe for stderr to child process.
+ int write_out_; // Pipe for stdin to child process.
+
+ char** program_arguments_;
+ intptr_t program_arguments_count_;
+ char** program_environment_;
+
+ mx_handle_t binary_vmo_;
+ launchpad_t* launchpad_;
+
+ const char* path_;
+ const char* working_directory_;
+ ProcessStartMode mode_;
+ intptr_t* in_;
+ intptr_t* out_;
+ intptr_t* err_;
+ intptr_t* id_;
+ intptr_t* exit_event_;
+ char** os_error_message_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter);
+};
+
+
int Process::Start(const char* path,
char* arguments[],
intptr_t arguments_length,
@@ -65,10 +672,28 @@ int Process::Start(const char* path,
intptr_t* id,
intptr_t* exit_event,
char** os_error_message) {
+ if (mode != kNormal) {
+ *os_error_message = DartUtils::ScopedCopyCString(
+ "Only ProcessStartMode.NORMAL is supported on this platform");
+ return -1;
+ }
+ ProcessStarter starter(path, arguments, arguments_length, working_directory,
+ environment, environment_length, mode, in, out, err,
+ id, exit_event, os_error_message);
+ return starter.Start();
+}
+
+
+intptr_t Process::SetSignalHandler(intptr_t signal) {
UNIMPLEMENTED();
return -1;
}
+
+void Process::ClearSignalHandler(intptr_t signal) {
+ UNIMPLEMENTED();
+}
+
} // namespace bin
} // namespace dart
« no previous file with comments | « runtime/bin/fdutils_fuchsia.cc ('k') | runtime/bin/socket_fuchsia.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698