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

Side by Side Diff: runtime/bin/process_fuchsia.cc

Issue 2563463002: Fuchsia: dart:io Processes (Closed)
Patch Set: Add const 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) : process_(process), fd_(fd) {}
56 ~ProcessInfo() {
57 int closed = NO_RETRY_EXPECTED(close(fd_));
58 if (closed != 0) {
59 FATAL("Failed to close process exit code pipe");
60 }
61 }
62 mx_handle_t process() const { return process_; }
63 intptr_t fd() const { return fd_; }
64 ProcessInfo* next() const { return next_; }
65 void set_next(ProcessInfo* info) { next_ = info; }
66
67 private:
68 mx_handle_t process_;
69 intptr_t fd_;
rmacnak 2016/12/12 18:18:20 exit_pipe_fd_
zra 2016/12/13 19:07:50 Done.
70 ProcessInfo* next_;
71
72 DISALLOW_COPY_AND_ASSIGN(ProcessInfo);
73 };
74
75
76 // Singly-linked list of ProcessInfo objects for all active processes
77 // started from Dart.
78 class ProcessInfoList {
79 public:
80 static void AddProcess(mx_handle_t process, intptr_t fd) {
81 MutexLocker locker(mutex_);
82 ProcessInfo* info = new ProcessInfo(process, fd);
83 info->set_next(active_processes_);
84 active_processes_ = info;
85 }
86
87
88 static intptr_t LookupProcessExitFd(mx_handle_t process) {
89 MutexLocker locker(mutex_);
90 ProcessInfo* current = active_processes_;
91 while (current != NULL) {
92 if (current->process() == process) {
93 return current->fd();
94 }
95 current = current->next();
96 }
97 return 0;
98 }
99
100
101 static void RemoveProcess(mx_handle_t process) {
102 MutexLocker locker(mutex_);
103 ProcessInfo* prev = NULL;
104 ProcessInfo* current = active_processes_;
105 while (current != NULL) {
106 if (current->process() == process) {
107 if (prev == NULL) {
108 active_processes_ = current->next();
109 } else {
110 prev->set_next(current->next());
111 }
112 delete current;
113 return;
114 }
115 prev = current;
116 current = current->next();
117 }
118 }
119
120 private:
121 // Linked list of ProcessInfo objects for all active processes
122 // started from Dart code.
123 static ProcessInfo* active_processes_;
124 // Mutex protecting all accesses to the linked list of active
125 // processes.
126 static Mutex* mutex_;
127
128 DISALLOW_ALLOCATION();
129 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList);
130 };
131
132 ProcessInfo* ProcessInfoList::active_processes_ = NULL;
133 Mutex* ProcessInfoList::mutex_ = new Mutex();
134
135 // The exit code handler sets up a separate thread which waits for child
136 // processes to terminate. That separate thread can then get the exit code from
137 // processes that have exited and communicate it to Dart through the
138 // event loop.
139 class ExitCodeHandler {
140 public:
141 // Notify the ExitCodeHandler that another process exists.
142 static void Start() {
143 // Multiple isolates could be starting processes at the same
144 // time. Make sure that only one ExitCodeHandler thread exists.
145 MonitorLocker locker(monitor_);
146 if (running_) {
147 return;
148 }
149
150 LOG_INFO("ExitCodeHandler Starting\n");
151
152 mx_status_t status = mx_socket_create(0, &interrupt_in_, &interrupt_out_);
153 if (status < 0) {
154 FATAL1("Failed to create exit code handler interrupt socket: %s\n",
155 mx_status_get_string(status));
156 }
157
158 // Start thread that handles process exits when wait returns.
159 intptr_t result = Thread::Start(
160 ExitCodeHandlerEntry, static_cast<uword>(interrupt_out_));
161 if (result != 0) {
162 FATAL1("Failed to start exit code handler worker thread %ld", result);
163 }
164
165 running_ = true;
166 }
167
168 static void Add(mx_handle_t process) {
169 MonitorLocker locker(monitor_);
170 LOG_INFO("ExitCodeHandler Adding Process: %ld\n", process);
171 SendMessage(Message::kAdd, process);
172 }
173
174 static void Terminate() {
175 MonitorLocker locker(monitor_);
176 if (!running_) {
177 return;
178 }
179 running_ = false;
180
181 LOG_INFO("ExitCodeHandler Terminating\n");
182 SendMessage(Message::kShutdown, MX_HANDLE_INVALID);
183
184 while (!terminate_done_) {
185 monitor_->Wait(Monitor::kNoTimeout);
186 }
187 mx_handle_close(interrupt_in_);
188 LOG_INFO("ExitCodeHandler Terminated\n");
189 }
190
191 private:
192 class Message {
193 public:
194 enum MessageId {
195 kAdd,
196 kShutdown,
197 };
198 MessageId id;
rmacnak 2016/12/12 18:18:20 id -> type/kind/command
zra 2016/12/13 19:07:50 Done.
199 mx_handle_t handle;
200 };
201
202 static void SendMessage(Message::MessageId id, mx_handle_t handle) {
203 Message msg;
204 msg.id = id;
205 msg.handle = handle;
206 size_t actual;
207 mx_status_t status =
208 mx_socket_write(interrupt_in_, 0, &msg, sizeof(msg), &actual);
209 if (status < 0) {
210 FATAL1("Write to exit handler interrupt handle failed: %s\n",
211 mx_status_get_string(status));
212 }
213 ASSERT(actual == sizeof(msg));
214 }
215
216 // Entry point for the separate exit code handler thread started by
217 // the ExitCodeHandler.
218 static void ExitCodeHandlerEntry(uword param) {
219 LOG_INFO("ExitCodeHandler Entering ExitCodeHandler thread\n");
220 item_capacity_ = 16;
221 items_ = reinterpret_cast<mx_wait_item_t*>(
222 malloc(item_capacity_ * sizeof(*items_)));
223 items_to_remove_ = reinterpret_cast<intptr_t*>(
224 malloc(item_capacity_ * sizeof(*items_to_remove_)));
225
226 // The interrupt handle is fixed to the first entry.
227 items_[0].handle = interrupt_out_;
228 items_[0].waitfor = MX_SOCKET_READABLE | MX_SOCKET_PEER_CLOSED;
229 items_[0].pending = MX_SIGNAL_NONE;
230 item_count_ = 1;
231
232 while (!do_shutdown_) {
233 LOG_INFO("ExitCodeHandler Calling mx_handle_wait_many: %ld items\n",
234 item_count_);
235 mx_status_t status =
236 mx_handle_wait_many(items_, item_count_, MX_TIME_INFINITE);
237 if (status < 0) {
238 FATAL1("Exit code handler handle wait failed: %s\n",
239 mx_status_get_string(status));
240 }
241 LOG_INFO("ExitCodeHandler mx_handle_wait_many returned\n");
242
243 bool have_interrupt = false;
244 intptr_t remove_count = 0;
245 for (intptr_t i = 0; i < item_count_; i++) {
246 if (items_[i].pending == MX_SIGNAL_NONE) {
247 continue;
248 }
249 if (i == 0) {
250 LOG_INFO("ExitCodeHandler thread saw interrupt\n");
251 have_interrupt = true;
252 continue;
253 }
254 ASSERT(items_[i].waitfor == MX_TASK_TERMINATED);
255 ASSERT((items_[i].pending & MX_TASK_TERMINATED) != 0);
256 LOG_INFO("ExitCodeHandler signal for %ld\n", items_[i].handle);
257 SendProcessStatus(items_[i].handle);
258 items_to_remove_[remove_count++] = i;
259 }
260 for (intptr_t i = 0; i < remove_count; i++) {
261 RemoveItem(items_to_remove_[i]);
262 }
263 if (have_interrupt) {
264 HandleInterruptMsg();
265 }
266 }
267
268 LOG_INFO("ExitCodeHandler thread shutting down\n");
269 mx_handle_close(interrupt_out_);
270 free(items_);
271 items_ = NULL;
272 free(items_to_remove_);
273 items_to_remove_ = NULL;
274 item_count_ = 0;
275 item_capacity_ = 0;
276
277 terminate_done_ = true;
278 monitor_->Notify();
279 }
280
281 static void SendProcessStatus(mx_handle_t process) {
282 LOG_INFO("ExitCodeHandler thread getting process status: %ld\n", process);
283 mx_info_process_t proc_info;
284 mx_status_t status = mx_object_get_info(
285 process, MX_INFO_PROCESS, &proc_info, sizeof(proc_info), NULL, NULL);
286 if (status < 0) {
287 FATAL1("mx_object_get_info failed on process handle: %s\n",
288 mx_status_get_string(status));
289 }
290
291 const int return_code = proc_info.return_code;
292 status = mx_handle_close(process);
293 if (status < 0) {
294 FATAL1("Failed to close process handle: %s\n",
295 mx_status_get_string(status));
296 }
297 LOG_INFO("ExitCodeHandler thread process %ld exited with %d\n",
298 process, return_code);
299
300 const intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(process);
301 LOG_INFO("ExitCodeHandler thread sending %ld code %d on fd %ld\n",
302 process, return_code, exit_code_fd);
303 if (exit_code_fd != 0) {
304 int exit_message[2];
305 exit_message[0] = return_code;
306 exit_message[1] = 0; // Do not negate return_code.
307 intptr_t result = FDUtils::WriteToBlocking(
308 exit_code_fd, &exit_message, sizeof(exit_message));
309 ASSERT((result == -1) || (result == sizeof(exit_code_fd)));
310 if ((result == -1) && (errno != EPIPE)) {
311 int err = errno;
312 FATAL1("Failed to write exit code to pipe: %d\n", err);
313 }
314 LOG_INFO("ExitCodeHandler thread wrote %ld bytes to fd %ld\n",
315 result, exit_code_fd);
316 LOG_INFO("ExitCodeHandler thread removing process %ld from list\n",
317 process);
318 ProcessInfoList::RemoveProcess(process);
319 }
320 }
321
322 static void HandleInterruptMsg() {
323 ASSERT(items_[0].handle == interrupt_out_);
324 ASSERT(items_[0].waitfor == MX_SOCKET_READABLE);
325 ASSERT((items_[0].pending & MX_SOCKET_READABLE) != 0);
326 while (true) {
327 Message msg;
328 size_t actual = 0;
329 LOG_INFO("ExitCodeHandler thread reading interrupt message\n");
330 mx_status_t status =
331 mx_socket_read(interrupt_out_, 0, &msg, sizeof(msg), &actual);
332 if (status == ERR_SHOULD_WAIT) {
333 LOG_INFO("ExitCodeHandler thread done reading interrupt messages\n");
334 return;
335 }
336 if (status < 0) {
337 FATAL1("Failed to read exit handler interrupt handle: %s\n",
338 mx_status_get_string(status));
339 }
340 if (actual < sizeof(msg)) {
341 FATAL1("Short read from exit handler interrupt handle: %ld\n",
342 actual);
343 }
344 switch (msg.id) {
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_ = reinterpret_cast<mx_wait_item_t*>(
361 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",
470 path, 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", \
579 __FILE__, __LINE__, 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 = launchpad_arguments(
597 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 status = launchpad_clone_mxio_root(lp);
604 CHECK_FOR_ERROR(status, "launchpad_clone_mxio_root");
605
606 status = launchpad_add_pipe(lp, &write_out_, 0);
607 CHECK_FOR_ERROR(status, "launchpad_add_pipe");
608
609 status = launchpad_add_pipe(lp, &read_in_, 1);
610 CHECK_FOR_ERROR(status, "launchpad_add_pipe");
611
612 status = launchpad_add_pipe(lp, &read_err_, 2);
613 CHECK_FOR_ERROR(status, "launchpad_add_pipe");
614
615 status = launchpad_add_vdso_vmo(lp);
616 CHECK_FOR_ERROR(status, "launchpad_add_vdso_vmo");
617
618 status = launchpad_elf_load(lp, binary_vmo);
619 CHECK_FOR_ERROR(status, "launchpad_elf_load");
620 binary_vmo_ = MX_HANDLE_INVALID; // launchpad_elf_load consumes the handle.
621
622 status = launchpad_load_vdso(lp, MX_HANDLE_INVALID);
623 CHECK_FOR_ERROR(status, "launchpad_load_vdso");
624
625 status = launchpad_clone_mxio_cwd(lp);
626 CHECK_FOR_ERROR(status, "launchpad_clone_mxio_cwd");
rmacnak 2016/12/12 18:18:21 Add a TODO to use the supplied working directory w
zra 2016/12/13 19:07:50 Done.
627
628 return NO_ERROR;
629 }
630
631 #undef CHECK_FOR_ERROR
632
633 int read_in_; // Pipe for stdout to child process.
634 int read_err_; // Pipe for stderr to child process.
635 int write_out_; // Pipe for stdin to child process.
636
637 char** program_arguments_;
638 intptr_t program_arguments_count_;
639 char** program_environment_;
640
641 mx_handle_t binary_vmo_;
642 launchpad_t* launchpad_;
643
644 const char* path_;
645 const char* working_directory_;
646 ProcessStartMode mode_;
647 intptr_t* in_;
648 intptr_t* out_;
649 intptr_t* err_;
650 intptr_t* id_;
651 intptr_t* exit_event_;
652 char** os_error_message_;
653
654 DISALLOW_ALLOCATION();
655 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter);
656 };
657
658
55 int Process::Start(const char* path, 659 int Process::Start(const char* path,
56 char* arguments[], 660 char* arguments[],
57 intptr_t arguments_length, 661 intptr_t arguments_length,
58 const char* working_directory, 662 const char* working_directory,
59 char* environment[], 663 char* environment[],
60 intptr_t environment_length, 664 intptr_t environment_length,
61 ProcessStartMode mode, 665 ProcessStartMode mode,
62 intptr_t* in, 666 intptr_t* in,
63 intptr_t* out, 667 intptr_t* out,
64 intptr_t* err, 668 intptr_t* err,
65 intptr_t* id, 669 intptr_t* id,
66 intptr_t* exit_event, 670 intptr_t* exit_event,
67 char** os_error_message) { 671 char** os_error_message) {
672 if (mode != kNormal) {
673 *os_error_message = DartUtils::ScopedCopyCString(
674 "Only ProcessStartMode.NORMAL is supported on this platform");
675 return -1;
676 }
677 ProcessStarter starter(path, arguments, arguments_length, working_directory,
678 environment, environment_length, mode, in, out, err,
679 id, exit_event, os_error_message);
680 return starter.Start();
681 }
682
683
684 intptr_t Process::SetSignalHandler(intptr_t signal) {
68 UNIMPLEMENTED(); 685 UNIMPLEMENTED();
69 return -1; 686 return -1;
70 } 687 }
71 688
689
690 void Process::ClearSignalHandler(intptr_t signal) {
691 UNIMPLEMENTED();
692 }
693
72 } // namespace bin 694 } // namespace bin
73 } // namespace dart 695 } // namespace dart
74 696
75 #endif // defined(TARGET_OS_FUCHSIA) 697 #endif // defined(TARGET_OS_FUCHSIA)
76 698
77 #endif // !defined(DART_IO_DISABLED) 699 #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