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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « runtime/bin/fdutils_fuchsia.cc ('k') | runtime/bin/socket_fuchsia.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #if !defined(DART_IO_DISABLED) 5 #if !defined(DART_IO_DISABLED)
6 6
7 #include "platform/globals.h" 7 #include "platform/globals.h"
8 #if defined(TARGET_OS_FUCHSIA) 8 #if defined(TARGET_OS_FUCHSIA)
9 9
10 #include "bin/process.h" 10 #include "bin/process.h"
11 11
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <launchpad/launchpad.h>
15 #include <launchpad/vmo.h>
16 #include <magenta/status.h>
17 #include <magenta/syscalls.h>
18 #include <magenta/syscalls/object.h>
19 #include <mxio/util.h>
20 #include <pthread.h>
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "bin/dartutils.h"
28 #include "bin/fdutils.h"
12 #include "bin/lockers.h" 29 #include "bin/lockers.h"
13 #include "platform/assert.h" 30 #include "bin/log.h"
31 #include "platform/signal_blocker.h"
14 32
33 // #define PROCESS_LOGGING 1
34 #if defined(PROCESS_LOGGING)
35 #define LOG_ERR(msg, ...) Log::PrintErr("Dart Process: " msg, ##__VA_ARGS__)
36 #define LOG_INFO(msg, ...) Log::Print("Dart Process: " msg, ##__VA_ARGS__)
37 #else
38 #define LOG_ERR(msg, ...)
39 #define LOG_INFO(msg, ...)
40 #endif // defined(PROCESS_LOGGING)
15 41
16 namespace dart { 42 namespace dart {
17 namespace bin { 43 namespace bin {
18 44
19 int Process::global_exit_code_ = 0; 45 int Process::global_exit_code_ = 0;
20 Mutex* Process::global_exit_code_mutex_ = new Mutex(); 46 Mutex* Process::global_exit_code_mutex_ = new Mutex();
21 Process::ExitHook Process::exit_hook_ = NULL; 47 Process::ExitHook Process::exit_hook_ = NULL;
22 48
23 void Process::TerminateExitCodeHandler() {} 49 // ProcessInfo is used to map a process id to the file descriptor for
50 // the pipe used to communicate the exit code of the process to Dart.
51 // ProcessInfo objects are kept in the static singly-linked
52 // ProcessInfoList.
53 class ProcessInfo {
54 public:
55 ProcessInfo(mx_handle_t process, intptr_t fd)
56 : process_(process), exit_pipe_fd_(fd) {}
57 ~ProcessInfo() {
58 int closed = NO_RETRY_EXPECTED(close(exit_pipe_fd_));
59 if (closed != 0) {
60 FATAL("Failed to close process exit code pipe");
61 }
62 }
63 mx_handle_t process() const { return process_; }
64 intptr_t exit_pipe_fd() const { return exit_pipe_fd_; }
65 ProcessInfo* next() const { return next_; }
66 void set_next(ProcessInfo* info) { next_ = info; }
67
68 private:
69 mx_handle_t process_;
70 intptr_t exit_pipe_fd_;
71 ProcessInfo* next_;
72
73 DISALLOW_COPY_AND_ASSIGN(ProcessInfo);
74 };
75
76
77 // Singly-linked list of ProcessInfo objects for all active processes
78 // started from Dart.
79 class ProcessInfoList {
80 public:
81 static void AddProcess(mx_handle_t process, intptr_t fd) {
82 MutexLocker locker(mutex_);
83 ProcessInfo* info = new ProcessInfo(process, fd);
84 info->set_next(active_processes_);
85 active_processes_ = info;
86 }
87
88
89 static intptr_t LookupProcessExitFd(mx_handle_t process) {
90 MutexLocker locker(mutex_);
91 ProcessInfo* current = active_processes_;
92 while (current != NULL) {
93 if (current->process() == process) {
94 return current->exit_pipe_fd();
95 }
96 current = current->next();
97 }
98 return 0;
99 }
100
101
102 static void RemoveProcess(mx_handle_t process) {
103 MutexLocker locker(mutex_);
104 ProcessInfo* prev = NULL;
105 ProcessInfo* current = active_processes_;
106 while (current != NULL) {
107 if (current->process() == process) {
108 if (prev == NULL) {
109 active_processes_ = current->next();
110 } else {
111 prev->set_next(current->next());
112 }
113 delete current;
114 return;
115 }
116 prev = current;
117 current = current->next();
118 }
119 }
120
121 private:
122 // Linked list of ProcessInfo objects for all active processes
123 // started from Dart code.
124 static ProcessInfo* active_processes_;
125 // Mutex protecting all accesses to the linked list of active
126 // processes.
127 static Mutex* mutex_;
128
129 DISALLOW_ALLOCATION();
130 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList);
131 };
132
133 ProcessInfo* ProcessInfoList::active_processes_ = NULL;
134 Mutex* ProcessInfoList::mutex_ = new Mutex();
135
136 // The exit code handler sets up a separate thread which waits for child
137 // processes to terminate. That separate thread can then get the exit code from
138 // processes that have exited and communicate it to Dart through the
139 // event loop.
140 class ExitCodeHandler {
141 public:
142 // Notify the ExitCodeHandler that another process exists.
143 static void Start() {
144 // Multiple isolates could be starting processes at the same
145 // time. Make sure that only one ExitCodeHandler thread exists.
146 MonitorLocker locker(monitor_);
147 if (running_) {
148 return;
149 }
150
151 LOG_INFO("ExitCodeHandler Starting\n");
152
153 mx_status_t status = mx_socket_create(0, &interrupt_in_, &interrupt_out_);
154 if (status < 0) {
155 FATAL1("Failed to create exit code handler interrupt socket: %s\n",
156 mx_status_get_string(status));
157 }
158
159 // Start thread that handles process exits when wait returns.
160 intptr_t result =
161 Thread::Start(ExitCodeHandlerEntry, static_cast<uword>(interrupt_out_));
162 if (result != 0) {
163 FATAL1("Failed to start exit code handler worker thread %ld", result);
164 }
165
166 running_ = true;
167 }
168
169 static void Add(mx_handle_t process) {
170 MonitorLocker locker(monitor_);
171 LOG_INFO("ExitCodeHandler Adding Process: %ld\n", process);
172 SendMessage(Message::kAdd, process);
173 }
174
175 static void Terminate() {
176 MonitorLocker locker(monitor_);
177 if (!running_) {
178 return;
179 }
180 running_ = false;
181
182 LOG_INFO("ExitCodeHandler Terminating\n");
183 SendMessage(Message::kShutdown, MX_HANDLE_INVALID);
184
185 while (!terminate_done_) {
186 monitor_->Wait(Monitor::kNoTimeout);
187 }
188 mx_handle_close(interrupt_in_);
189 LOG_INFO("ExitCodeHandler Terminated\n");
190 }
191
192 private:
193 class Message {
194 public:
195 enum Command {
196 kAdd,
197 kShutdown,
198 };
199 Command command;
200 mx_handle_t handle;
201 };
202
203 static void SendMessage(Message::Command command, mx_handle_t handle) {
204 Message msg;
205 msg.command = command;
206 msg.handle = handle;
207 size_t actual;
208 mx_status_t status =
209 mx_socket_write(interrupt_in_, 0, &msg, sizeof(msg), &actual);
210 if (status < 0) {
211 FATAL1("Write to exit handler interrupt handle failed: %s\n",
212 mx_status_get_string(status));
213 }
214 ASSERT(actual == sizeof(msg));
215 }
216
217 // Entry point for the separate exit code handler thread started by
218 // the ExitCodeHandler.
219 static void ExitCodeHandlerEntry(uword param) {
220 LOG_INFO("ExitCodeHandler Entering ExitCodeHandler thread\n");
221 item_capacity_ = 16;
222 items_ = reinterpret_cast<mx_wait_item_t*>(
223 malloc(item_capacity_ * sizeof(*items_)));
224 items_to_remove_ = reinterpret_cast<intptr_t*>(
225 malloc(item_capacity_ * sizeof(*items_to_remove_)));
226
227 // The interrupt handle is fixed to the first entry.
228 items_[0].handle = interrupt_out_;
229 items_[0].waitfor = MX_SOCKET_READABLE | MX_SOCKET_PEER_CLOSED;
230 items_[0].pending = MX_SIGNAL_NONE;
231 item_count_ = 1;
232
233 while (!do_shutdown_) {
234 LOG_INFO("ExitCodeHandler Calling mx_handle_wait_many: %ld items\n",
235 item_count_);
236 mx_status_t status =
237 mx_handle_wait_many(items_, item_count_, MX_TIME_INFINITE);
238 if (status < 0) {
239 FATAL1("Exit code handler handle wait failed: %s\n",
240 mx_status_get_string(status));
241 }
242 LOG_INFO("ExitCodeHandler mx_handle_wait_many returned\n");
243
244 bool have_interrupt = false;
245 intptr_t remove_count = 0;
246 for (intptr_t i = 0; i < item_count_; i++) {
247 if (items_[i].pending == MX_SIGNAL_NONE) {
248 continue;
249 }
250 if (i == 0) {
251 LOG_INFO("ExitCodeHandler thread saw interrupt\n");
252 have_interrupt = true;
253 continue;
254 }
255 ASSERT(items_[i].waitfor == MX_TASK_TERMINATED);
256 ASSERT((items_[i].pending & MX_TASK_TERMINATED) != 0);
257 LOG_INFO("ExitCodeHandler signal for %ld\n", items_[i].handle);
258 SendProcessStatus(items_[i].handle);
259 items_to_remove_[remove_count++] = i;
260 }
261 for (intptr_t i = 0; i < remove_count; i++) {
262 RemoveItem(items_to_remove_[i]);
263 }
264 if (have_interrupt) {
265 HandleInterruptMsg();
266 }
267 }
268
269 LOG_INFO("ExitCodeHandler thread shutting down\n");
270 mx_handle_close(interrupt_out_);
271 free(items_);
272 items_ = NULL;
273 free(items_to_remove_);
274 items_to_remove_ = NULL;
275 item_count_ = 0;
276 item_capacity_ = 0;
277
278 terminate_done_ = true;
279 monitor_->Notify();
280 }
281
282 static void SendProcessStatus(mx_handle_t process) {
283 LOG_INFO("ExitCodeHandler thread getting process status: %ld\n", process);
284 mx_info_process_t proc_info;
285 mx_status_t status = mx_object_get_info(
286 process, MX_INFO_PROCESS, &proc_info, sizeof(proc_info), NULL, NULL);
287 if (status < 0) {
288 FATAL1("mx_object_get_info failed on process handle: %s\n",
289 mx_status_get_string(status));
290 }
291
292 const int return_code = proc_info.return_code;
293 status = mx_handle_close(process);
294 if (status < 0) {
295 FATAL1("Failed to close process handle: %s\n",
296 mx_status_get_string(status));
297 }
298 LOG_INFO("ExitCodeHandler thread process %ld exited with %d\n", process,
299 return_code);
300
301 const intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(process);
302 LOG_INFO("ExitCodeHandler thread sending %ld code %d on fd %ld\n", process,
303 return_code, exit_code_fd);
304 if (exit_code_fd != 0) {
305 int exit_message[2];
306 exit_message[0] = return_code;
307 exit_message[1] = 0; // Do not negate return_code.
308 intptr_t result = FDUtils::WriteToBlocking(exit_code_fd, &exit_message,
309 sizeof(exit_message));
310 ASSERT((result == -1) || (result == sizeof(exit_code_fd)));
311 if ((result == -1) && (errno != EPIPE)) {
312 int err = errno;
313 FATAL1("Failed to write exit code to pipe: %d\n", err);
314 }
315 LOG_INFO("ExitCodeHandler thread wrote %ld bytes to fd %ld\n", result,
316 exit_code_fd);
317 LOG_INFO("ExitCodeHandler thread removing process %ld from list\n",
318 process);
319 ProcessInfoList::RemoveProcess(process);
320 }
321 }
322
323 static void HandleInterruptMsg() {
324 ASSERT(items_[0].handle == interrupt_out_);
325 ASSERT(items_[0].waitfor == MX_SOCKET_READABLE);
326 ASSERT((items_[0].pending & MX_SOCKET_READABLE) != 0);
327 while (true) {
328 Message msg;
329 size_t actual = 0;
330 LOG_INFO("ExitCodeHandler thread reading interrupt message\n");
331 mx_status_t status =
332 mx_socket_read(interrupt_out_, 0, &msg, sizeof(msg), &actual);
333 if (status == ERR_SHOULD_WAIT) {
334 LOG_INFO("ExitCodeHandler thread done reading interrupt messages\n");
335 return;
336 }
337 if (status < 0) {
338 FATAL1("Failed to read exit handler interrupt handle: %s\n",
339 mx_status_get_string(status));
340 }
341 if (actual < sizeof(msg)) {
342 FATAL1("Short read from exit handler interrupt handle: %ld\n", actual);
343 }
344 switch (msg.command) {
345 case Message::kShutdown:
346 LOG_INFO("ExitCodeHandler thread got shutdown message\n");
347 do_shutdown_ = true;
348 break;
349 case Message::kAdd:
350 LOG_INFO("ExitCodeHandler thread got add message: %ld\n", msg.handle);
351 AddItem(msg.handle);
352 break;
353 }
354 }
355 }
356
357 static void AddItem(mx_handle_t h) {
358 if (item_count_ == item_capacity_) {
359 item_capacity_ = item_capacity_ + (item_capacity_ >> 1);
360 items_ =
361 reinterpret_cast<mx_wait_item_t*>(realloc(items_, item_capacity_));
362 items_to_remove_ = reinterpret_cast<intptr_t*>(
363 realloc(items_to_remove_, item_capacity_));
364 }
365 LOG_INFO("ExitCodeHandler thread adding item %ld at %ld\n", h, item_count_);
366 items_[item_count_].handle = h;
367 items_[item_count_].waitfor = MX_TASK_TERMINATED;
368 items_[item_count_].pending = MX_SIGNAL_NONE;
369 item_count_++;
370 }
371
372 static void RemoveItem(intptr_t idx) {
373 LOG_INFO("ExitCodeHandler thread removing item %ld at %ld\n",
374 items_[idx].handle, idx);
375 ASSERT(idx != 0);
376 const intptr_t last = item_count_ - 1;
377 items_[idx].handle = MX_HANDLE_INVALID;
378 items_[idx].waitfor = MX_SIGNAL_NONE;
379 items_[idx].pending = MX_SIGNAL_NONE;
380 if (idx != last) {
381 items_[idx] = items_[last];
382 }
383 item_count_--;
384 }
385
386 // Interrupt message pipe.
387 static mx_handle_t interrupt_in_;
388 static mx_handle_t interrupt_out_;
389
390 // Accessed only by the ExitCodeHandler thread.
391 static mx_wait_item_t* items_;
392 static intptr_t* items_to_remove_;
393 static intptr_t item_count_;
394 static intptr_t item_capacity_;
395
396 // Protected by monitor_.
397 static bool do_shutdown_;
398 static bool terminate_done_;
399 static bool running_;
400 static Monitor* monitor_;
401
402 DISALLOW_ALLOCATION();
403 DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler);
404 };
405
406 mx_handle_t ExitCodeHandler::interrupt_in_ = MX_HANDLE_INVALID;
407 mx_handle_t ExitCodeHandler::interrupt_out_ = MX_HANDLE_INVALID;
408 mx_wait_item_t* ExitCodeHandler::items_ = NULL;
409 intptr_t* ExitCodeHandler::items_to_remove_ = NULL;
410 intptr_t ExitCodeHandler::item_count_ = 0;
411 intptr_t ExitCodeHandler::item_capacity_ = 0;
412
413 bool ExitCodeHandler::do_shutdown_ = false;
414 bool ExitCodeHandler::running_ = false;
415 bool ExitCodeHandler::terminate_done_ = false;
416 Monitor* ExitCodeHandler::monitor_ = new Monitor();
417
418 void Process::TerminateExitCodeHandler() {
419 ExitCodeHandler::Terminate();
420 }
421
24 422
25 intptr_t Process::CurrentProcessId() { 423 intptr_t Process::CurrentProcessId() {
26 UNIMPLEMENTED(); 424 return static_cast<intptr_t>(getpid());
27 return 0;
28 } 425 }
29 426
30 intptr_t Process::SetSignalHandler(intptr_t signal) {
31 UNIMPLEMENTED();
32 return -1;
33 }
34
35
36 void Process::ClearSignalHandler(intptr_t signal) {
37 UNIMPLEMENTED();
38 }
39 427
40 bool Process::Wait(intptr_t pid, 428 bool Process::Wait(intptr_t pid,
41 intptr_t in, 429 intptr_t in,
42 intptr_t out, 430 intptr_t out,
43 intptr_t err, 431 intptr_t err,
44 intptr_t exit_event, 432 intptr_t exit_event,
45 ProcessResult* result) { 433 ProcessResult* result) {
46 UNIMPLEMENTED(); 434 UNIMPLEMENTED();
47 return false; 435 return false;
48 } 436 }
49 437
438
50 bool Process::Kill(intptr_t id, int signal) { 439 bool Process::Kill(intptr_t id, int signal) {
51 UNIMPLEMENTED(); 440 UNIMPLEMENTED();
52 return false; 441 return false;
53 } 442 }
54 443
444
445 class ProcessStarter {
446 public:
447 ProcessStarter(const char* path,
448 char* arguments[],
449 intptr_t arguments_length,
450 const char* working_directory,
451 char* environment[],
452 intptr_t environment_length,
453 ProcessStartMode mode,
454 intptr_t* in,
455 intptr_t* out,
456 intptr_t* err,
457 intptr_t* id,
458 intptr_t* exit_event,
459 char** os_error_message)
460 : path_(path),
461 working_directory_(working_directory),
462 mode_(mode),
463 in_(in),
464 out_(out),
465 err_(err),
466 id_(id),
467 exit_event_(exit_event),
468 os_error_message_(os_error_message) {
469 LOG_INFO("ProcessStarter: ctor %s with %ld args, mode = %d\n", path,
470 arguments_length, mode);
471
472 read_in_ = -1;
473 read_err_ = -1;
474 write_out_ = -1;
475
476 program_arguments_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
477 (arguments_length + 2) * sizeof(*program_arguments_)));
478 program_arguments_[0] = const_cast<char*>(path_);
479 for (int i = 0; i < arguments_length; i++) {
480 program_arguments_[i + 1] = arguments[i];
481 }
482 program_arguments_[arguments_length + 1] = NULL;
483 program_arguments_count_ = arguments_length + 1;
484
485 program_environment_ = NULL;
486 if (environment != NULL) {
487 program_environment_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
488 (environment_length + 1) * sizeof(*program_environment_)));
489 for (int i = 0; i < environment_length; i++) {
490 program_environment_[i] = environment[i];
491 }
492 program_environment_[environment_length] = NULL;
493 }
494
495 binary_vmo_ = MX_HANDLE_INVALID;
496 launchpad_ = NULL;
497 }
498
499 ~ProcessStarter() {
500 if (binary_vmo_ != MX_HANDLE_INVALID) {
501 mx_handle_close(binary_vmo_);
502 }
503 if (launchpad_ != NULL) {
504 launchpad_destroy(launchpad_);
505 }
506 if (read_in_ != -1) {
507 close(read_in_);
508 }
509 if (read_err_ != -1) {
510 close(read_err_);
511 }
512 if (write_out_ != -1) {
513 close(write_out_);
514 }
515 }
516
517 int Start() {
518 LOG_INFO("ProcessStarter: Start()\n");
519 int exit_pipe_fds[2];
520 intptr_t result = NO_RETRY_EXPECTED(pipe(exit_pipe_fds));
521 if (result != 0) {
522 *os_error_message_ = DartUtils::ScopedCopyCString(
523 "Failed to create exit code pipe for process start.");
524 return result;
525 }
526 LOG_INFO("ProcessStarter: Start() set up exit_pipe_fds (%d, %d)\n",
527 exit_pipe_fds[0], exit_pipe_fds[1]);
528
529 mx_status_t status = SetupLaunchpad();
530 if (status != NO_ERROR) {
531 close(exit_pipe_fds[0]);
532 close(exit_pipe_fds[1]);
533 return status;
534 }
535
536 LOG_INFO("ProcessStarter: Start() Calling launchpad_start\n");
537 mx_handle_t process = launchpad_start(launchpad_);
538 launchpad_destroy(launchpad_);
539 launchpad_ = NULL;
540 if (process < 0) {
541 LOG_INFO("ProcessStarter: Start() launchpad_start failed\n");
542 const intptr_t kMaxMessageSize = 256;
543 close(exit_pipe_fds[0]);
544 close(exit_pipe_fds[1]);
545 char* message = DartUtils::ScopedCString(kMaxMessageSize);
546 snprintf(message, kMaxMessageSize, "%s:%d: launchpad_start failed: %s\n",
547 __FILE__, __LINE__, mx_status_get_string(process));
548 *os_error_message_ = message;
549 return process;
550 }
551
552 LOG_INFO("ProcessStarter: Start() adding %ld to list with exit_pipe %d\n",
553 process, exit_pipe_fds[1]);
554 ProcessInfoList::AddProcess(process, exit_pipe_fds[1]);
555 ExitCodeHandler::Start();
556 ExitCodeHandler::Add(process);
557
558 *id_ = process;
559 FDUtils::SetNonBlocking(read_in_);
560 *in_ = read_in_;
561 read_in_ = -1;
562 FDUtils::SetNonBlocking(read_err_);
563 *err_ = read_err_;
564 read_err_ = -1;
565 FDUtils::SetNonBlocking(write_out_);
566 *out_ = write_out_;
567 write_out_ = -1;
568 FDUtils::SetNonBlocking(exit_pipe_fds[0]);
569 *exit_event_ = exit_pipe_fds[0];
570 return 0;
571 }
572
573 private:
574 #define CHECK_FOR_ERROR(status, msg) \
575 if (status < 0) { \
576 const intptr_t kMaxMessageSize = 256; \
577 char* message = DartUtils::ScopedCString(kMaxMessageSize); \
578 snprintf(message, kMaxMessageSize, "%s:%d: %s: %s\n", __FILE__, __LINE__, \
579 msg, mx_status_get_string(status)); \
580 *os_error_message_ = message; \
581 return status; \
582 }
583
584 mx_status_t SetupLaunchpad() {
585 mx_handle_t binary_vmo = launchpad_vmo_from_file(path_);
586 CHECK_FOR_ERROR(binary_vmo, "launchpad_vmo_from_file");
587 binary_vmo_ = binary_vmo;
588
589 launchpad_t* lp;
590 mx_status_t status;
591
592 status = launchpad_create(0, program_arguments_[0], &lp);
593 CHECK_FOR_ERROR(status, "launchpad_create");
594 launchpad_ = lp;
595
596 status =
597 launchpad_arguments(lp, program_arguments_count_, program_arguments_);
598 CHECK_FOR_ERROR(status, "launchpad_arguments");
599
600 status = launchpad_environ(lp, program_environment_);
601 CHECK_FOR_ERROR(status, "launchpad_environ");
602
603 // TODO(zra): Use the supplied working directory when launchpad adds an
604 // API to set it.
605
606 status = launchpad_clone_mxio_root(lp);
607 CHECK_FOR_ERROR(status, "launchpad_clone_mxio_root");
608
609 status = launchpad_add_pipe(lp, &write_out_, 0);
610 CHECK_FOR_ERROR(status, "launchpad_add_pipe");
611
612 status = launchpad_add_pipe(lp, &read_in_, 1);
613 CHECK_FOR_ERROR(status, "launchpad_add_pipe");
614
615 status = launchpad_add_pipe(lp, &read_err_, 2);
616 CHECK_FOR_ERROR(status, "launchpad_add_pipe");
617
618 status = launchpad_add_vdso_vmo(lp);
619 CHECK_FOR_ERROR(status, "launchpad_add_vdso_vmo");
620
621 status = launchpad_elf_load(lp, binary_vmo);
622 CHECK_FOR_ERROR(status, "launchpad_elf_load");
623 binary_vmo_ = MX_HANDLE_INVALID; // launchpad_elf_load consumes the handle.
624
625 status = launchpad_load_vdso(lp, MX_HANDLE_INVALID);
626 CHECK_FOR_ERROR(status, "launchpad_load_vdso");
627
628 status = launchpad_clone_mxio_cwd(lp);
629 CHECK_FOR_ERROR(status, "launchpad_clone_mxio_cwd");
630
631 return NO_ERROR;
632 }
633
634 #undef CHECK_FOR_ERROR
635
636 int read_in_; // Pipe for stdout to child process.
637 int read_err_; // Pipe for stderr to child process.
638 int write_out_; // Pipe for stdin to child process.
639
640 char** program_arguments_;
641 intptr_t program_arguments_count_;
642 char** program_environment_;
643
644 mx_handle_t binary_vmo_;
645 launchpad_t* launchpad_;
646
647 const char* path_;
648 const char* working_directory_;
649 ProcessStartMode mode_;
650 intptr_t* in_;
651 intptr_t* out_;
652 intptr_t* err_;
653 intptr_t* id_;
654 intptr_t* exit_event_;
655 char** os_error_message_;
656
657 DISALLOW_ALLOCATION();
658 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter);
659 };
660
661
55 int Process::Start(const char* path, 662 int Process::Start(const char* path,
56 char* arguments[], 663 char* arguments[],
57 intptr_t arguments_length, 664 intptr_t arguments_length,
58 const char* working_directory, 665 const char* working_directory,
59 char* environment[], 666 char* environment[],
60 intptr_t environment_length, 667 intptr_t environment_length,
61 ProcessStartMode mode, 668 ProcessStartMode mode,
62 intptr_t* in, 669 intptr_t* in,
63 intptr_t* out, 670 intptr_t* out,
64 intptr_t* err, 671 intptr_t* err,
65 intptr_t* id, 672 intptr_t* id,
66 intptr_t* exit_event, 673 intptr_t* exit_event,
67 char** os_error_message) { 674 char** os_error_message) {
675 if (mode != kNormal) {
676 *os_error_message = DartUtils::ScopedCopyCString(
677 "Only ProcessStartMode.NORMAL is supported on this platform");
678 return -1;
679 }
680 ProcessStarter starter(path, arguments, arguments_length, working_directory,
681 environment, environment_length, mode, in, out, err,
682 id, exit_event, os_error_message);
683 return starter.Start();
684 }
685
686
687 intptr_t Process::SetSignalHandler(intptr_t signal) {
68 UNIMPLEMENTED(); 688 UNIMPLEMENTED();
69 return -1; 689 return -1;
70 } 690 }
71 691
692
693 void Process::ClearSignalHandler(intptr_t signal) {
694 UNIMPLEMENTED();
695 }
696
72 } // namespace bin 697 } // namespace bin
73 } // namespace dart 698 } // namespace dart
74 699
75 #endif // defined(TARGET_OS_FUCHSIA) 700 #endif // defined(TARGET_OS_FUCHSIA)
76 701
77 #endif // !defined(DART_IO_DISABLED) 702 #endif // !defined(DART_IO_DISABLED)
OLDNEW
« 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