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

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

Issue 2910853002: [Fuchsia] EventHandler: epoll -> ports v2 (Closed)
Patch Set: Fix typo Created 3 years, 6 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 | « runtime/bin/eventhandler_fuchsia.cc ('k') | runtime/bin/socket_base_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(HOST_OS_FUCHSIA) 8 #if defined(HOST_OS_FUCHSIA)
9 9
10 #include "bin/process.h" 10 #include "bin/process.h"
(...skipping 11 matching lines...) Expand all
22 #include <mxio/util.h> 22 #include <mxio/util.h>
23 #include <pthread.h> 23 #include <pthread.h>
24 #include <stdbool.h> 24 #include <stdbool.h>
25 #include <stdio.h> 25 #include <stdio.h>
26 #include <stdlib.h> 26 #include <stdlib.h>
27 #include <string.h> 27 #include <string.h>
28 #include <sys/epoll.h> 28 #include <sys/epoll.h>
29 #include <unistd.h> 29 #include <unistd.h>
30 30
31 #include "bin/dartutils.h" 31 #include "bin/dartutils.h"
32 #include "bin/eventhandler.h"
32 #include "bin/fdutils.h" 33 #include "bin/fdutils.h"
33 #include "bin/lockers.h" 34 #include "bin/lockers.h"
34 #include "bin/log.h" 35 #include "bin/log.h"
35 #include "platform/signal_blocker.h" 36 #include "platform/signal_blocker.h"
36 #include "platform/utils.h" 37 #include "platform/utils.h"
37 38
38 // #define PROCESS_LOGGING 1 39 // #define PROCESS_LOGGING 1
39 #if defined(PROCESS_LOGGING) 40 #if defined(PROCESS_LOGGING)
40 #define LOG_ERR(msg, ...) Log::PrintErr("Dart Process: " msg, ##__VA_ARGS__) 41 #define LOG_ERR(msg, ...) Log::PrintErr("Dart Process: " msg, ##__VA_ARGS__)
41 #define LOG_INFO(msg, ...) Log::Print("Dart Process: " msg, ##__VA_ARGS__) 42 #define LOG_INFO(msg, ...) Log::Print("Dart Process: " msg, ##__VA_ARGS__)
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 } 448 }
448 449
449 450
450 int64_t Process::MaxRSS() { 451 int64_t Process::MaxRSS() {
451 // There is currently no way to get the high watermark value on Fuchsia, so 452 // There is currently no way to get the high watermark value on Fuchsia, so
452 // just return the current RSS value. 453 // just return the current RSS value.
453 return CurrentRSS(); 454 return CurrentRSS();
454 } 455 }
455 456
456 457
457 static bool ProcessWaitCleanup(intptr_t out, 458 class IOHandleScope {
458 intptr_t err,
459 intptr_t exit_event) {
460 int e = errno;
461 VOID_NO_RETRY_EXPECTED(close(out));
462 VOID_NO_RETRY_EXPECTED(close(err));
463 VOID_NO_RETRY_EXPECTED(close(exit_event));
464 errno = e;
465 return false;
466 }
467
468
469 class MxioWaitEntry {
470 public: 459 public:
471 MxioWaitEntry() {} 460 explicit IOHandleScope(IOHandle* io_handle) : io_handle_(io_handle) {}
472 ~MxioWaitEntry() { Cancel(); } 461 ~IOHandleScope() {
473 462 io_handle_->Close();
474 void Init(int fd) { mxio_ = __mxio_fd_to_io(fd); } 463 io_handle_->Release();
475
476 void WaitBegin(mx_wait_item_t* wait_item) {
477 if (mxio_ == NULL) {
478 *wait_item = {};
479 return;
480 }
481
482 __mxio_wait_begin(mxio_, EPOLLRDHUP | EPOLLIN, &wait_item->handle,
483 &wait_item->waitfor);
484 wait_item->pending = 0;
485 }
486
487 void WaitEnd(mx_wait_item_t* wait_item, uint32_t* event) {
488 if (mxio_ == NULL) {
489 *event = 0;
490 return;
491 }
492 __mxio_wait_end(mxio_, wait_item->pending, event);
493 }
494
495 void Cancel() {
496 if (mxio_ != NULL) {
497 __mxio_release(mxio_);
498 }
499 mxio_ = NULL;
500 } 464 }
501 465
502 private: 466 private:
503 mxio_t* mxio_ = NULL; 467 IOHandle* io_handle_;
504 468
505 DISALLOW_COPY_AND_ASSIGN(MxioWaitEntry); 469 DISALLOW_ALLOCATION();
470 DISALLOW_COPY_AND_ASSIGN(IOHandleScope);
506 }; 471 };
507 472
508 473
509 bool Process::Wait(intptr_t pid, 474 bool Process::Wait(intptr_t pid,
510 intptr_t in, 475 intptr_t in,
511 intptr_t out, 476 intptr_t out,
512 intptr_t err, 477 intptr_t err,
513 intptr_t exit_event, 478 intptr_t exit_event,
514 ProcessResult* result) { 479 ProcessResult* result) {
515 VOID_NO_RETRY_EXPECTED(close(in)); 480 // input not needed.
481 IOHandle* in_iohandle = reinterpret_cast<IOHandle*>(in);
482 in_iohandle->Close();
483 in_iohandle->Release();
484 in_iohandle = NULL;
485
486 IOHandle* out_iohandle = reinterpret_cast<IOHandle*>(out);
487 IOHandle* err_iohandle = reinterpret_cast<IOHandle*>(err);
488 IOHandle* exit_iohandle = reinterpret_cast<IOHandle*>(exit_event);
489 IOHandleScope out_ioscope(out_iohandle);
490 IOHandleScope err_ioscope(err_iohandle);
491 IOHandleScope exit_ioscope(exit_iohandle);
516 492
517 // There is no return from this function using Dart_PropagateError 493 // There is no return from this function using Dart_PropagateError
518 // as memory used by the buffer lists is freed through their 494 // as memory used by the buffer lists is freed through their
519 // destructors. 495 // destructors.
520 BufferList out_data; 496 BufferList out_data;
521 BufferList err_data; 497 BufferList err_data;
522 union { 498 union {
523 uint8_t bytes[8]; 499 uint8_t bytes[8];
524 int32_t ints[2]; 500 int32_t ints[2];
525 } exit_code_data; 501 } exit_code_data;
526 502
527 constexpr size_t kWaitItemsCount = 3; 503 // Create a port, which is like an epoll() fd on Linux.
528 uint32_t events[kWaitItemsCount]; 504 mx_handle_t port;
529 mx_wait_item_t wait_items[kWaitItemsCount]; 505 mx_status_t status = mx_port_create(MX_PORT_OPT_V2, &port);
530 size_t active = kWaitItemsCount; 506 if (status != MX_OK) {
507 Log::PrintErr("Process::Wait: mx_port_create failed: %s\n",
508 mx_status_get_string(status));
509 return false;
510 }
531 511
532 MxioWaitEntry entries[kWaitItemsCount]; 512 IOHandle* out_tmp = out_iohandle;
533 entries[0].Init(out); 513 IOHandle* err_tmp = err_iohandle;
534 entries[1].Init(err); 514 IOHandle* exit_tmp = exit_iohandle;
535 entries[2].Init(exit_event); 515 const uint64_t out_key = reinterpret_cast<uint64_t>(out_tmp);
536 516 const uint64_t err_key = reinterpret_cast<uint64_t>(err_tmp);
537 while (active > 0) { 517 const uint64_t exit_key = reinterpret_cast<uint64_t>(exit_tmp);
538 for (size_t i = 0; i < kWaitItemsCount; ++i) { 518 const uint32_t events = EPOLLRDHUP | EPOLLIN;
539 entries[i].WaitBegin(&wait_items[i]); 519 if (!out_tmp->AsyncWait(port, events, out_key)) {
520 return false;
521 }
522 if (!err_tmp->AsyncWait(port, events, err_key)) {
523 return false;
524 }
525 if (!exit_tmp->AsyncWait(port, events, exit_key)) {
526 return false;
527 }
528 while ((out_tmp != NULL) || (err_tmp != NULL) || (exit_tmp != NULL)) {
529 mx_port_packet_t pkt;
530 status =
531 mx_port_wait(port, MX_TIME_INFINITE, reinterpret_cast<void*>(&pkt), 0);
532 if (status != MX_OK) {
533 Log::PrintErr("Process::Wait: mx_port_wait failed: %s\n",
534 mx_status_get_string(status));
535 return false;
540 } 536 }
541 mx_object_wait_many(wait_items, kWaitItemsCount, MX_TIME_INFINITE); 537 IOHandle* event_handle = reinterpret_cast<IOHandle*>(pkt.key);
542 538 const intptr_t event_mask = event_handle->WaitEnd(pkt.signal.observed);
543 for (size_t i = 0; i < kWaitItemsCount; ++i) { 539 if (event_handle == out_tmp) {
544 entries[i].WaitEnd(&wait_items[i], &events[i]); 540 if ((event_mask & EPOLLIN) != 0) {
541 const intptr_t avail = FDUtils::AvailableBytes(out_tmp->fd());
542 if (!out_data.Read(out_tmp->fd(), avail)) {
543 return false;
544 }
545 }
546 if ((event_mask & EPOLLRDHUP) != 0) {
547 out_tmp->CancelWait(port, out_key);
548 out_tmp = NULL;
549 }
550 } else if (event_handle == err_tmp) {
551 if ((event_mask & EPOLLIN) != 0) {
552 const intptr_t avail = FDUtils::AvailableBytes(err_tmp->fd());
553 if (!err_data.Read(err_tmp->fd(), avail)) {
554 return false;
555 }
556 }
557 if ((event_mask & EPOLLRDHUP) != 0) {
558 err_tmp->CancelWait(port, err_key);
559 err_tmp = NULL;
560 }
561 } else if (event_handle == exit_tmp) {
562 if ((event_mask & EPOLLIN) != 0) {
563 const intptr_t avail = FDUtils::AvailableBytes(exit_tmp->fd());
564 if (avail == 8) {
565 intptr_t b =
566 NO_RETRY_EXPECTED(read(exit_tmp->fd(), exit_code_data.bytes, 8));
567 if (b != 8) {
568 return false;
569 }
570 }
571 }
572 if ((event_mask & EPOLLRDHUP) != 0) {
573 exit_tmp->CancelWait(port, exit_key);
574 exit_tmp = NULL;
575 }
576 } else {
577 Log::PrintErr("Process::Wait: Unexpected wait key: %p\n", event_handle);
545 } 578 }
546 579 if (out_tmp != NULL) {
547 if ((events[0] & EPOLLIN) != 0) { 580 if (!out_tmp->AsyncWait(port, events, out_key)) {
548 const intptr_t avail = FDUtils::AvailableBytes(out); 581 return false;
549 if (!out_data.Read(out, avail)) {
550 return ProcessWaitCleanup(out, err, exit_event);
551 } 582 }
552 } 583 }
553 if ((events[1] & EPOLLIN) != 0) { 584 if (err_tmp != NULL) {
554 const intptr_t avail = FDUtils::AvailableBytes(err); 585 if (!err_tmp->AsyncWait(port, events, err_key)) {
555 if (!err_data.Read(err, avail)) { 586 return false;
556 return ProcessWaitCleanup(out, err, exit_event);
557 } 587 }
558 } 588 }
559 if ((events[2] & EPOLLIN) != 0) { 589 if (exit_tmp != NULL) {
560 const intptr_t avail = FDUtils::AvailableBytes(exit_event); 590 if (!exit_tmp->AsyncWait(port, events, exit_key)) {
561 if (avail == 8) { 591 return false;
562 intptr_t b =
563 NO_RETRY_EXPECTED(read(exit_event, exit_code_data.bytes, 8));
564 if (b != 8) {
565 return ProcessWaitCleanup(out, err, exit_event);
566 }
567 }
568 }
569 for (size_t i = 0; i < kWaitItemsCount; ++i) {
570 if ((events[i] & EPOLLRDHUP) != 0) {
571 active--;
572 entries[i].Cancel();
573 } 592 }
574 } 593 }
575 } 594 }
576 595
577 // All handles closed and all data read. 596 // All handles closed and all data read.
578 result->set_stdout_data(out_data.GetData()); 597 result->set_stdout_data(out_data.GetData());
579 result->set_stderr_data(err_data.GetData()); 598 result->set_stderr_data(err_data.GetData());
580 DEBUG_ASSERT(out_data.IsEmpty()); 599 DEBUG_ASSERT(out_data.IsEmpty());
581 DEBUG_ASSERT(err_data.IsEmpty()); 600 DEBUG_ASSERT(err_data.IsEmpty());
582 601
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 *os_error_message_ = message; 743 *os_error_message_ = message;
725 return status; 744 return status;
726 } 745 }
727 746
728 LOG_INFO("ProcessStarter: Start() adding %ld to list with exit_pipe %d\n", 747 LOG_INFO("ProcessStarter: Start() adding %ld to list with exit_pipe %d\n",
729 process, exit_pipe_fds[1]); 748 process, exit_pipe_fds[1]);
730 ProcessInfoList::AddProcess(process, exit_pipe_fds[1]); 749 ProcessInfoList::AddProcess(process, exit_pipe_fds[1]);
731 ExitCodeHandler::Start(); 750 ExitCodeHandler::Start();
732 ExitCodeHandler::Add(process); 751 ExitCodeHandler::Add(process);
733 752
753 // The IOHandles allocated below are returned to Dart code. The Dart code
754 // calls into the runtime again to allocate a C++ Socket object, which
755 // becomes the native field of a Dart _NativeSocket object. The C++ Socket
756 // object and the EventHandler manage the lifetime of these IOHandles.
734 *id_ = process; 757 *id_ = process;
735 FDUtils::SetNonBlocking(read_in_); 758 FDUtils::SetNonBlocking(read_in_);
736 *in_ = read_in_; 759 *in_ = reinterpret_cast<intptr_t>(new IOHandle(read_in_));
737 read_in_ = -1; 760 read_in_ = -1;
738 FDUtils::SetNonBlocking(read_err_); 761 FDUtils::SetNonBlocking(read_err_);
739 *err_ = read_err_; 762 *err_ = reinterpret_cast<intptr_t>(new IOHandle(read_err_));
740 read_err_ = -1; 763 read_err_ = -1;
741 FDUtils::SetNonBlocking(write_out_); 764 FDUtils::SetNonBlocking(write_out_);
742 *out_ = write_out_; 765 *out_ = reinterpret_cast<intptr_t>(new IOHandle(write_out_));
743 write_out_ = -1; 766 write_out_ = -1;
744 FDUtils::SetNonBlocking(exit_pipe_fds[0]); 767 FDUtils::SetNonBlocking(exit_pipe_fds[0]);
745 *exit_event_ = exit_pipe_fds[0]; 768 *exit_event_ = reinterpret_cast<intptr_t>(new IOHandle(exit_pipe_fds[0]));
746 return 0; 769 return 0;
747 } 770 }
748 771
749 private: 772 private:
750 #define CHECK_FOR_ERROR(status, msg) \ 773 #define CHECK_FOR_ERROR(status, msg) \
751 if (status < 0) { \ 774 if (status < 0) { \
752 const intptr_t kMaxMessageSize = 256; \ 775 const intptr_t kMaxMessageSize = 256; \
753 char* message = DartUtils::ScopedCString(kMaxMessageSize); \ 776 char* message = DartUtils::ScopedCString(kMaxMessageSize); \
754 snprintf(message, kMaxMessageSize, "%s:%d: %s: %s\n", __FILE__, __LINE__, \ 777 snprintf(message, kMaxMessageSize, "%s:%d: %s: %s\n", __FILE__, __LINE__, \
755 msg, mx_status_get_string(status)); \ 778 msg, mx_status_get_string(status)); \
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 } 868 }
846 869
847 void Process::ClearSignalHandler(intptr_t signal) {} 870 void Process::ClearSignalHandler(intptr_t signal) {}
848 871
849 } // namespace bin 872 } // namespace bin
850 } // namespace dart 873 } // namespace dart
851 874
852 #endif // defined(HOST_OS_FUCHSIA) 875 #endif // defined(HOST_OS_FUCHSIA)
853 876
854 #endif // !defined(DART_IO_DISABLED) 877 #endif // !defined(DART_IO_DISABLED)
OLDNEW
« no previous file with comments | « runtime/bin/eventhandler_fuchsia.cc ('k') | runtime/bin/socket_base_fuchsia.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698