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

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

Issue 2903373003: [fuchsia] Replace use of epoll with mx_ primitives in process_fuchsia (Closed)
Patch Set: Created 3 years, 7 months 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 | « no previous file | no next file » | 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(HOST_OS_FUCHSIA) 8 #if defined(HOST_OS_FUCHSIA)
9 9
10 #include "bin/process.h" 10 #include "bin/process.h"
11 11
12 #include <errno.h> 12 #include <errno.h>
13 #include <fcntl.h> 13 #include <fcntl.h>
14 #include <launchpad/launchpad.h> 14 #include <launchpad/launchpad.h>
15 #include <launchpad/vmo.h> 15 #include <launchpad/vmo.h>
16 #include <magenta/process.h> 16 #include <magenta/process.h>
17 #include <magenta/status.h> 17 #include <magenta/status.h>
18 #include <magenta/syscalls.h> 18 #include <magenta/syscalls.h>
19 #include <magenta/syscalls/object.h> 19 #include <magenta/syscalls/object.h>
20 #include <magenta/types.h>
21 #include <mxio/private.h>
20 #include <mxio/util.h> 22 #include <mxio/util.h>
21 #include <pthread.h> 23 #include <pthread.h>
22 #include <stdbool.h> 24 #include <stdbool.h>
23 #include <stdio.h> 25 #include <stdio.h>
24 #include <stdlib.h> 26 #include <stdlib.h>
25 #include <string.h> 27 #include <string.h>
26 #include <sys/epoll.h> 28 #include <sys/epoll.h>
27 #include <unistd.h> 29 #include <unistd.h>
28 30
29 #include "bin/dartutils.h" 31 #include "bin/dartutils.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 void set_next(ProcessInfo* info) { next_ = info; } 72 void set_next(ProcessInfo* info) { next_ = info; }
71 73
72 private: 74 private:
73 mx_handle_t process_; 75 mx_handle_t process_;
74 intptr_t exit_pipe_fd_; 76 intptr_t exit_pipe_fd_;
75 ProcessInfo* next_; 77 ProcessInfo* next_;
76 78
77 DISALLOW_COPY_AND_ASSIGN(ProcessInfo); 79 DISALLOW_COPY_AND_ASSIGN(ProcessInfo);
78 }; 80 };
79 81
80
81 // Singly-linked list of ProcessInfo objects for all active processes 82 // Singly-linked list of ProcessInfo objects for all active processes
82 // started from Dart. 83 // started from Dart.
83 class ProcessInfoList { 84 class ProcessInfoList {
84 public: 85 public:
85 static void AddProcess(mx_handle_t process, intptr_t fd) { 86 static void AddProcess(mx_handle_t process, intptr_t fd) {
86 MutexLocker locker(mutex_); 87 MutexLocker locker(mutex_);
87 ProcessInfo* info = new ProcessInfo(process, fd); 88 ProcessInfo* info = new ProcessInfo(process, fd);
88 info->set_next(active_processes_); 89 info->set_next(active_processes_);
89 active_processes_ = info; 90 active_processes_ = info;
90 } 91 }
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 419
419 bool ExitCodeHandler::do_shutdown_ = false; 420 bool ExitCodeHandler::do_shutdown_ = false;
420 bool ExitCodeHandler::running_ = false; 421 bool ExitCodeHandler::running_ = false;
421 bool ExitCodeHandler::terminate_done_ = false; 422 bool ExitCodeHandler::terminate_done_ = false;
422 Monitor* ExitCodeHandler::monitor_ = new Monitor(); 423 Monitor* ExitCodeHandler::monitor_ = new Monitor();
423 424
424 void Process::TerminateExitCodeHandler() { 425 void Process::TerminateExitCodeHandler() {
425 ExitCodeHandler::Terminate(); 426 ExitCodeHandler::Terminate();
426 } 427 }
427 428
428
zra 2017/05/26 16:13:22 Dart VM style is two newlines between top-level fu
jamesr1 2017/05/27 00:14:09 Turns out I wasn't reading your .clang-format file
429 intptr_t Process::CurrentProcessId() { 429 intptr_t Process::CurrentProcessId() {
430 return static_cast<intptr_t>(getpid()); 430 return static_cast<intptr_t>(getpid());
431 } 431 }
432 432
433
434 int64_t Process::CurrentRSS() { 433 int64_t Process::CurrentRSS() {
435 mx_info_task_stats_t task_stats; 434 mx_info_task_stats_t task_stats;
436 mx_handle_t process = mx_process_self(); 435 mx_handle_t process = mx_process_self();
437 mx_status_t status = mx_object_get_info( 436 mx_status_t status = mx_object_get_info(
438 process, MX_INFO_TASK_STATS, &task_stats, sizeof(task_stats), NULL, NULL); 437 process, MX_INFO_TASK_STATS, &task_stats, sizeof(task_stats), NULL, NULL);
439 if (status != NO_ERROR) { 438 if (status != NO_ERROR) {
440 // TODO(zra): Translate this to a Unix errno. 439 // TODO(zra): Translate this to a Unix errno.
441 errno = status; 440 errno = status;
442 return -1; 441 return -1;
443 } 442 }
444 return task_stats.mem_committed_bytes; 443 return task_stats.mem_committed_bytes;
445 } 444 }
446 445
447
448 int64_t Process::MaxRSS() { 446 int64_t Process::MaxRSS() {
449 // There is currently no way to get the high watermark value on Fuchsia, so 447 // There is currently no way to get the high watermark value on Fuchsia, so
450 // just return the current RSS value. 448 // just return the current RSS value.
451 return CurrentRSS(); 449 return CurrentRSS();
452 } 450 }
453 451
454
455 static bool ProcessWaitCleanup(intptr_t out, 452 static bool ProcessWaitCleanup(intptr_t out,
456 intptr_t err, 453 intptr_t err,
457 intptr_t exit_event, 454 intptr_t exit_event) {
458 intptr_t epoll_fd) {
459 int e = errno; 455 int e = errno;
460 VOID_NO_RETRY_EXPECTED(close(out)); 456 VOID_NO_RETRY_EXPECTED(close(out));
461 VOID_NO_RETRY_EXPECTED(close(err)); 457 VOID_NO_RETRY_EXPECTED(close(err));
462 VOID_NO_RETRY_EXPECTED(close(exit_event)); 458 VOID_NO_RETRY_EXPECTED(close(exit_event));
463 VOID_NO_RETRY_EXPECTED(close(epoll_fd));
464 errno = e; 459 errno = e;
465 return false; 460 return false;
466 } 461 }
467 462
463 class MxioWaitEntry {
464 public:
465 explicit MxioWaitEntry(int fd) : mxio_(__mxio_fd_to_io(fd)) {}
466 ~MxioWaitEntry() { Cancel(); }
467
468 void WaitBegin(mx_wait_item_t* wait_item) {
469 if (mxio_ == nullptr) {
zra 2017/05/26 16:13:22 To be consistent with the rest of the VM, please u
jamesr1 2017/05/27 00:14:10 done
470 *wait_item = {};
471 return;
472 }
473
474 __mxio_wait_begin(mxio_, EPOLLRDHUP | EPOLLIN, &wait_item->handle,
475 &wait_item->waitfor);
476 wait_item->pending = 0;
477 }
478
479 void WaitEnd(mx_wait_item_t* wait_item, uint32_t* event) {
480 if (mxio_ == nullptr) {
481 *event = 0;
482 return;
483 }
484 __mxio_wait_end(mxio_, wait_item->pending, event);
485 }
486
487 void Cancel() {
488 if (mxio_)
zra 2017/05/26 16:13:22 if (mxio_ != NULL) Also, please use curly braces
jamesr1 2017/05/27 00:14:10 done
489 __mxio_release(mxio_);
490 mxio_ = nullptr;
491 }
492
493 private:
494 mxio_t* mxio_;
495 };
zra 2017/05/26 16:13:22 Maybe DISALLOW_COPY_AND_ASSIGN(MxioWaitEntry) or D
jamesr1 2017/05/27 00:14:10 done
468 496
469 bool Process::Wait(intptr_t pid, 497 bool Process::Wait(intptr_t pid,
470 intptr_t in, 498 intptr_t in,
471 intptr_t out, 499 intptr_t out,
472 intptr_t err, 500 intptr_t err,
473 intptr_t exit_event, 501 intptr_t exit_event,
474 ProcessResult* result) { 502 ProcessResult* result) {
475 VOID_NO_RETRY_EXPECTED(close(in)); 503 VOID_NO_RETRY_EXPECTED(close(in));
476 504
477 // There is no return from this function using Dart_PropagateError 505 // There is no return from this function using Dart_PropagateError
478 // as memory used by the buffer lists is freed through their 506 // as memory used by the buffer lists is freed through their
479 // destructors. 507 // destructors.
480 BufferList out_data; 508 BufferList out_data;
481 BufferList err_data; 509 BufferList err_data;
482 union { 510 union {
483 uint8_t bytes[8]; 511 uint8_t bytes[8];
484 int32_t ints[2]; 512 int32_t ints[2];
485 } exit_code_data; 513 } exit_code_data;
486 514
487 // The initial size passed to epoll_create is ignore on newer (>= 515 uint32_t events[3];
488 // 2.6.8) Linux versions 516 mx_wait_item_t wait_items[3];
zra 2017/05/26 16:13:22 const intptr_t kWaitItemsCount = 3;
jamesr1 2017/05/27 00:14:10 done
489 static const int kEpollInitialSize = 64; 517 size_t active = 3;
490 int epoll_fd = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize));
491 if (epoll_fd == -1) {
492 return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
493 }
494 if (!FDUtils::SetCloseOnExec(epoll_fd)) {
495 return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
496 }
497 518
498 struct epoll_event event; 519 MxioWaitEntry entries[3] = {
499 event.events = EPOLLRDHUP | EPOLLIN; 520 MxioWaitEntry(out), MxioWaitEntry(err), MxioWaitEntry(exit_event),
500 event.data.fd = out; 521 };
501 int status = NO_RETRY_EXPECTED(
502 epoll_ctl(epoll_fd, EPOLL_CTL_ADD, out, &event));
503 if (status == -1) {
504 return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
505 }
506 event.data.fd = err;
507 status = NO_RETRY_EXPECTED(
508 epoll_ctl(epoll_fd, EPOLL_CTL_ADD, err, &event));
509 if (status == -1) {
510 return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
511 }
512 event.data.fd = exit_event;
513 status = NO_RETRY_EXPECTED(
514 epoll_ctl(epoll_fd, EPOLL_CTL_ADD, exit_event, &event));
515 if (status == -1) {
516 return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
517 }
518 intptr_t active = 3;
519 522
520 static const intptr_t kMaxEvents = 16;
521 struct epoll_event events[kMaxEvents];
522 while (active > 0) { 523 while (active > 0) {
523 // TODO(US-109): When the epoll implementation is properly edge-triggered, 524 // TODO(US-109): When the epoll implementation is properly edge-triggered,
524 // remove this sleep, which prevents the message queue from being 525 // remove this sleep, which prevents the message queue from being
525 // overwhelmed and leading to memory exhaustion. 526 // overwhelmed and leading to memory exhaustion.
526 usleep(5000); 527 usleep(5000);
zra 2017/05/26 16:13:22 This was copy-pasted from the eventhandler, but pr
jamesr1 2017/05/27 00:14:10 done
527 intptr_t result = NO_RETRY_EXPECTED( 528
528 epoll_wait(epoll_fd, events, kMaxEvents, -1)); 529 for (size_t i = 0; i < 3; ++i) {
529 if ((result < 0) && (errno != EWOULDBLOCK)) { 530 entries[i].WaitBegin(&wait_items[i]);
530 return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
531 } 531 }
532 for (intptr_t i = 0; i < result; i++) { 532 mx_object_wait_many(wait_items, 3, MX_TIME_INFINITE);
533 if ((events[i].events & EPOLLIN) != 0) { 533
534 const intptr_t avail = FDUtils::AvailableBytes(events[i].data.fd); 534 for (size_t i = 0; i < 3; ++i) {
535 if (events[i].data.fd == out) { 535 entries[i].WaitEnd(&wait_items[i], &events[i]);
536 if (!out_data.Read(out, avail)) { 536 }
537 return ProcessWaitCleanup(out, err, exit_event, epoll_fd); 537
538 } 538 if ((events[0] & EPOLLIN) != 0) {
539 } else if (events[i].data.fd == err) { 539 const intptr_t avail = FDUtils::AvailableBytes(out);
540 if (!err_data.Read(err, avail)) { 540 if (!out_data.Read(out, avail)) {
541 return ProcessWaitCleanup(out, err, exit_event, epoll_fd); 541 return ProcessWaitCleanup(out, err, exit_event);
542 } 542 }
543 } else if (events[i].data.fd == exit_event) { 543 }
544 if (avail == 8) { 544 if ((events[1] & EPOLLIN) != 0) {
545 intptr_t b = 545 const intptr_t avail = FDUtils::AvailableBytes(err);
546 NO_RETRY_EXPECTED(read(exit_event, exit_code_data.bytes, 8)); 546 if (!err_data.Read(err, avail)) {
547 if (b != 8) { 547 return ProcessWaitCleanup(err, err, exit_event);
548 return ProcessWaitCleanup(out, err, exit_event, epoll_fd); 548 }
549 } 549 }
550 } 550 if ((events[2] & EPOLLIN) != 0) {
551 } else { 551 const intptr_t avail = FDUtils::AvailableBytes(exit_event);
552 UNREACHABLE(); 552 if (avail == 8) {
553 intptr_t b =
554 NO_RETRY_EXPECTED(read(exit_event, exit_code_data.bytes, 8));
555 if (b != 8) {
556 return ProcessWaitCleanup(out, err, exit_event);
553 } 557 }
554 } 558 }
555 if ((events[i].events & (EPOLLHUP | EPOLLRDHUP)) != 0) { 559 }
556 NO_RETRY_EXPECTED(close(events[i].data.fd)); 560 for (size_t i = 0; i < 3; ++i) {
561 if ((events[i] & EPOLLRDHUP) != 0) {
557 active--; 562 active--;
558 VOID_NO_RETRY_EXPECTED( 563 entries[i].Cancel();
559 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd, NULL));
560 } 564 }
561 } 565 }
562 } 566 }
563 VOID_NO_RETRY_EXPECTED(close(epoll_fd));
564 567
565 // All handles closed and all data read. 568 // All handles closed and all data read.
566 result->set_stdout_data(out_data.GetData()); 569 result->set_stdout_data(out_data.GetData());
567 result->set_stderr_data(err_data.GetData()); 570 result->set_stderr_data(err_data.GetData());
568 DEBUG_ASSERT(out_data.IsEmpty()); 571 DEBUG_ASSERT(out_data.IsEmpty());
569 DEBUG_ASSERT(err_data.IsEmpty()); 572 DEBUG_ASSERT(err_data.IsEmpty());
570 573
571 // Calculate the exit code. 574 // Calculate the exit code.
572 intptr_t exit_code = exit_code_data.ints[0]; 575 intptr_t exit_code = exit_code_data.ints[0];
573 intptr_t negative = exit_code_data.ints[1]; 576 intptr_t negative = exit_code_data.ints[1];
574 if (negative != 0) { 577 if (negative != 0) {
575 exit_code = -exit_code; 578 exit_code = -exit_code;
576 } 579 }
577 result->set_exit_code(exit_code); 580 result->set_exit_code(exit_code);
578 581
579 // Close the process handle. 582 // Close the process handle.
580 mx_handle_t process = static_cast<mx_handle_t>(pid); 583 mx_handle_t process = static_cast<mx_handle_t>(pid);
581 mx_handle_close(process); 584 mx_handle_close(process);
582 return true; 585 return true;
583 } 586 }
584 587
585
586 bool Process::Kill(intptr_t id, int signal) { 588 bool Process::Kill(intptr_t id, int signal) {
587 LOG_INFO("Sending signal %d to process with id %ld\n", signal, id); 589 LOG_INFO("Sending signal %d to process with id %ld\n", signal, id);
588 // mx_task_kill is definitely going to kill the process. 590 // mx_task_kill is definitely going to kill the process.
589 if ((signal != SIGTERM) && (signal != SIGKILL)) { 591 if ((signal != SIGTERM) && (signal != SIGKILL)) {
590 LOG_ERR("Signal %d not supported\n", signal); 592 LOG_ERR("Signal %d not supported\n", signal);
591 errno = ENOSYS; 593 errno = ENOSYS;
592 return false; 594 return false;
593 } 595 }
594 // We can only use mx_task_kill if we know id is a process handle, and we only 596 // We can only use mx_task_kill if we know id is a process handle, and we only
595 // know that for sure if it's in our list. 597 // know that for sure if it's in our list.
596 mx_handle_t process = static_cast<mx_handle_t>(id); 598 mx_handle_t process = static_cast<mx_handle_t>(id);
597 if (!ProcessInfoList::Exists(process)) { 599 if (!ProcessInfoList::Exists(process)) {
598 LOG_ERR("Process %ld wasn't in the ProcessInfoList\n", id); 600 LOG_ERR("Process %ld wasn't in the ProcessInfoList\n", id);
599 errno = ESRCH; // No such process. 601 errno = ESRCH; // No such process.
600 return false; 602 return false;
601 } 603 }
602 mx_status_t status = mx_task_kill(process); 604 mx_status_t status = mx_task_kill(process);
603 if (status != NO_ERROR) { 605 if (status != NO_ERROR) {
604 LOG_ERR("mx_task_kill failed: %s\n", mx_status_get_string(status)); 606 LOG_ERR("mx_task_kill failed: %s\n", mx_status_get_string(status));
605 errno = EPERM; // TODO(zra): Figure out what it really should be. 607 errno = EPERM; // TODO(zra): Figure out what it really should be.
606 return false; 608 return false;
607 } 609 }
608 LOG_INFO("Signal %d sent successfully to process %ld\n", signal, id); 610 LOG_INFO("Signal %d sent successfully to process %ld\n", signal, id);
609 return true; 611 return true;
610 } 612 }
611 613
612
613 class ProcessStarter { 614 class ProcessStarter {
614 public: 615 public:
615 ProcessStarter(const char* path, 616 ProcessStarter(const char* path,
616 char* arguments[], 617 char* arguments[],
617 intptr_t arguments_length, 618 intptr_t arguments_length,
618 const char* working_directory, 619 const char* working_directory,
619 char* environment[], 620 char* environment[],
620 intptr_t environment_length, 621 intptr_t environment_length,
621 ProcessStartMode mode, 622 ProcessStartMode mode,
622 intptr_t* in, 623 intptr_t* in,
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 read_err_ = -1; 729 read_err_ = -1;
729 FDUtils::SetNonBlocking(write_out_); 730 FDUtils::SetNonBlocking(write_out_);
730 *out_ = write_out_; 731 *out_ = write_out_;
731 write_out_ = -1; 732 write_out_ = -1;
732 FDUtils::SetNonBlocking(exit_pipe_fds[0]); 733 FDUtils::SetNonBlocking(exit_pipe_fds[0]);
733 *exit_event_ = exit_pipe_fds[0]; 734 *exit_event_ = exit_pipe_fds[0];
734 return 0; 735 return 0;
735 } 736 }
736 737
737 private: 738 private:
738 #define CHECK_FOR_ERROR(status, msg) \ 739 #define CHECK_FOR_ERROR(status, msg) \
zra 2017/05/26 16:13:22 It looks like the escaped newlines were already in
739 if (status < 0) { \ 740 if (status < 0) { \
740 const intptr_t kMaxMessageSize = 256; \ 741 const intptr_t kMaxMessageSize = 256; \
741 char* message = DartUtils::ScopedCString(kMaxMessageSize); \ 742 char* message = DartUtils::ScopedCString(kMaxMessageSize); \
742 snprintf(message, kMaxMessageSize, "%s:%d: %s: %s\n", __FILE__, __LINE__, \ 743 snprintf(message, kMaxMessageSize, "%s:%d: %s: %s\n", __FILE__, __LINE__, \
743 msg, mx_status_get_string(status)); \ 744 msg, mx_status_get_string(status)); \
744 *os_error_message_ = message; \ 745 *os_error_message_ = message; \
745 return status; \ 746 return status; \
746 } 747 }
747 748
748 mx_status_t SetupLaunchpad(launchpad_t** launchpad) { 749 mx_status_t SetupLaunchpad(launchpad_t** launchpad) {
749 // Set up a vmo for the binary. 750 // Set up a vmo for the binary.
750 mx_handle_t binary_vmo = launchpad_vmo_from_file(path_); 751 mx_handle_t binary_vmo = launchpad_vmo_from_file(path_);
751 CHECK_FOR_ERROR(binary_vmo, "launchpad_vmo_from_file"); 752 CHECK_FOR_ERROR(binary_vmo, "launchpad_vmo_from_file");
752 753
753 // Run the child process in the same "job". 754 // Run the child process in the same "job".
754 mx_handle_t job = MX_HANDLE_INVALID; 755 mx_handle_t job = MX_HANDLE_INVALID;
755 mx_status_t status = 756 mx_status_t status =
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 intptr_t* out_; 796 intptr_t* out_;
796 intptr_t* err_; 797 intptr_t* err_;
797 intptr_t* id_; 798 intptr_t* id_;
798 intptr_t* exit_event_; 799 intptr_t* exit_event_;
799 char** os_error_message_; 800 char** os_error_message_;
800 801
801 DISALLOW_ALLOCATION(); 802 DISALLOW_ALLOCATION();
802 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter); 803 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter);
803 }; 804 };
804 805
805
806 int Process::Start(const char* path, 806 int Process::Start(const char* path,
807 char* arguments[], 807 char* arguments[],
808 intptr_t arguments_length, 808 intptr_t arguments_length,
809 const char* working_directory, 809 const char* working_directory,
810 char* environment[], 810 char* environment[],
811 intptr_t environment_length, 811 intptr_t environment_length,
812 ProcessStartMode mode, 812 ProcessStartMode mode,
813 intptr_t* in, 813 intptr_t* in,
814 intptr_t* out, 814 intptr_t* out,
815 intptr_t* err, 815 intptr_t* err,
816 intptr_t* id, 816 intptr_t* id,
817 intptr_t* exit_event, 817 intptr_t* exit_event,
818 char** os_error_message) { 818 char** os_error_message) {
819 if (mode != kNormal) { 819 if (mode != kNormal) {
820 *os_error_message = DartUtils::ScopedCopyCString( 820 *os_error_message = DartUtils::ScopedCopyCString(
821 "Only ProcessStartMode.NORMAL is supported on this platform"); 821 "Only ProcessStartMode.NORMAL is supported on this platform");
822 return -1; 822 return -1;
823 } 823 }
824 ProcessStarter starter(path, arguments, arguments_length, working_directory, 824 ProcessStarter starter(path, arguments, arguments_length, working_directory,
825 environment, environment_length, mode, in, out, err, 825 environment, environment_length, mode, in, out, err,
826 id, exit_event, os_error_message); 826 id, exit_event, os_error_message);
827 return starter.Start(); 827 return starter.Start();
828 } 828 }
829 829
830
831 intptr_t Process::SetSignalHandler(intptr_t signal) { 830 intptr_t Process::SetSignalHandler(intptr_t signal) {
832 errno = ENOSYS; 831 errno = ENOSYS;
833 return -1; 832 return -1;
834 } 833 }
835 834
836 835 void Process::ClearSignalHandler(intptr_t signal) {}
837 void Process::ClearSignalHandler(intptr_t signal) {
838 }
839 836
840 } // namespace bin 837 } // namespace bin
841 } // namespace dart 838 } // namespace dart
842 839
843 #endif // defined(HOST_OS_FUCHSIA) 840 #endif // defined(HOST_OS_FUCHSIA)
844 841
845 #endif // !defined(DART_IO_DISABLED) 842 #endif // !defined(DART_IO_DISABLED)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698