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

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: [fuchsia] Replace use of epoll with mx_ primitives in process_fuchsia 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 | « 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 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 449
448 int64_t Process::MaxRSS() { 450 int64_t Process::MaxRSS() {
449 // There is currently no way to get the high watermark value on Fuchsia, so 451 // There is currently no way to get the high watermark value on Fuchsia, so
450 // just return the current RSS value. 452 // just return the current RSS value.
451 return CurrentRSS(); 453 return CurrentRSS();
452 } 454 }
453 455
454 456
455 static bool ProcessWaitCleanup(intptr_t out, 457 static bool ProcessWaitCleanup(intptr_t out,
456 intptr_t err, 458 intptr_t err,
457 intptr_t exit_event, 459 intptr_t exit_event) {
458 intptr_t epoll_fd) {
459 int e = errno; 460 int e = errno;
460 VOID_NO_RETRY_EXPECTED(close(out)); 461 VOID_NO_RETRY_EXPECTED(close(out));
461 VOID_NO_RETRY_EXPECTED(close(err)); 462 VOID_NO_RETRY_EXPECTED(close(err));
462 VOID_NO_RETRY_EXPECTED(close(exit_event)); 463 VOID_NO_RETRY_EXPECTED(close(exit_event));
463 VOID_NO_RETRY_EXPECTED(close(epoll_fd));
464 errno = e; 464 errno = e;
465 return false; 465 return false;
466 } 466 }
467 467
468 468
469 class MxioWaitEntry {
470 public:
471 MxioWaitEntry() {}
472 ~MxioWaitEntry() { Cancel(); }
473
474 void Init(int fd) { mxio_ = __mxio_fd_to_io(fd); }
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 }
501
502 private:
503 mxio_t* mxio_ = NULL;
504
505 DISALLOW_COPY_AND_ASSIGN(MxioWaitEntry);
506 };
507
508
469 bool Process::Wait(intptr_t pid, 509 bool Process::Wait(intptr_t pid,
470 intptr_t in, 510 intptr_t in,
471 intptr_t out, 511 intptr_t out,
472 intptr_t err, 512 intptr_t err,
473 intptr_t exit_event, 513 intptr_t exit_event,
474 ProcessResult* result) { 514 ProcessResult* result) {
475 VOID_NO_RETRY_EXPECTED(close(in)); 515 VOID_NO_RETRY_EXPECTED(close(in));
476 516
477 // There is no return from this function using Dart_PropagateError 517 // There is no return from this function using Dart_PropagateError
478 // as memory used by the buffer lists is freed through their 518 // as memory used by the buffer lists is freed through their
479 // destructors. 519 // destructors.
480 BufferList out_data; 520 BufferList out_data;
481 BufferList err_data; 521 BufferList err_data;
482 union { 522 union {
483 uint8_t bytes[8]; 523 uint8_t bytes[8];
484 int32_t ints[2]; 524 int32_t ints[2];
485 } exit_code_data; 525 } exit_code_data;
486 526
487 // The initial size passed to epoll_create is ignore on newer (>= 527 constexpr size_t kWaitItemsCount = 3;
488 // 2.6.8) Linux versions 528 uint32_t events[kWaitItemsCount];
489 static const int kEpollInitialSize = 64; 529 mx_wait_item_t wait_items[kWaitItemsCount];
490 int epoll_fd = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize)); 530 size_t active = kWaitItemsCount;
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 531
498 struct epoll_event event; 532 MxioWaitEntry entries[kWaitItemsCount];
499 event.events = EPOLLRDHUP | EPOLLIN; 533 entries[0].Init(out);
500 event.data.fd = out; 534 entries[1].Init(err);
501 int status = NO_RETRY_EXPECTED( 535 entries[2].Init(exit_event);
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 536
520 static const intptr_t kMaxEvents = 16;
521 struct epoll_event events[kMaxEvents];
522 while (active > 0) { 537 while (active > 0) {
523 // TODO(US-109): When the epoll implementation is properly edge-triggered, 538 for (size_t i = 0; i < kWaitItemsCount; ++i) {
524 // remove this sleep, which prevents the message queue from being 539 entries[i].WaitBegin(&wait_items[i]);
525 // overwhelmed and leading to memory exhaustion.
526 usleep(5000);
527 intptr_t result = NO_RETRY_EXPECTED(
528 epoll_wait(epoll_fd, events, kMaxEvents, -1));
529 if ((result < 0) && (errno != EWOULDBLOCK)) {
530 return ProcessWaitCleanup(out, err, exit_event, epoll_fd);
531 } 540 }
532 for (intptr_t i = 0; i < result; i++) { 541 mx_object_wait_many(wait_items, kWaitItemsCount, MX_TIME_INFINITE);
533 if ((events[i].events & EPOLLIN) != 0) { 542
534 const intptr_t avail = FDUtils::AvailableBytes(events[i].data.fd); 543 for (size_t i = 0; i < kWaitItemsCount; ++i) {
535 if (events[i].data.fd == out) { 544 entries[i].WaitEnd(&wait_items[i], &events[i]);
536 if (!out_data.Read(out, avail)) { 545 }
537 return ProcessWaitCleanup(out, err, exit_event, epoll_fd); 546
538 } 547 if ((events[0] & EPOLLIN) != 0) {
539 } else if (events[i].data.fd == err) { 548 const intptr_t avail = FDUtils::AvailableBytes(out);
540 if (!err_data.Read(err, avail)) { 549 if (!out_data.Read(out, avail)) {
541 return ProcessWaitCleanup(out, err, exit_event, epoll_fd); 550 return ProcessWaitCleanup(out, err, exit_event);
542 } 551 }
543 } else if (events[i].data.fd == exit_event) { 552 }
544 if (avail == 8) { 553 if ((events[1] & EPOLLIN) != 0) {
545 intptr_t b = 554 const intptr_t avail = FDUtils::AvailableBytes(err);
546 NO_RETRY_EXPECTED(read(exit_event, exit_code_data.bytes, 8)); 555 if (!err_data.Read(err, avail)) {
547 if (b != 8) { 556 return ProcessWaitCleanup(err, err, exit_event);
kulakowski1 2017/05/30 20:47:55 The change from ProcessWaitCleanup(out, err, exit_
jamesr1 2017/05/30 20:53:58 Yup, that's a typo. Fixed!
548 return ProcessWaitCleanup(out, err, exit_event, epoll_fd); 557 }
549 } 558 }
550 } 559 if ((events[2] & EPOLLIN) != 0) {
551 } else { 560 const intptr_t avail = FDUtils::AvailableBytes(exit_event);
552 UNREACHABLE(); 561 if (avail == 8) {
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);
553 } 566 }
554 } 567 }
555 if ((events[i].events & (EPOLLHUP | EPOLLRDHUP)) != 0) { 568 }
556 NO_RETRY_EXPECTED(close(events[i].data.fd)); 569 for (size_t i = 0; i < kWaitItemsCount; ++i) {
570 if ((events[i] & EPOLLRDHUP) != 0) {
557 active--; 571 active--;
558 VOID_NO_RETRY_EXPECTED( 572 entries[i].Cancel();
559 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd, NULL));
560 } 573 }
561 } 574 }
562 } 575 }
563 VOID_NO_RETRY_EXPECTED(close(epoll_fd));
564 576
565 // All handles closed and all data read. 577 // All handles closed and all data read.
566 result->set_stdout_data(out_data.GetData()); 578 result->set_stdout_data(out_data.GetData());
567 result->set_stderr_data(err_data.GetData()); 579 result->set_stderr_data(err_data.GetData());
568 DEBUG_ASSERT(out_data.IsEmpty()); 580 DEBUG_ASSERT(out_data.IsEmpty());
569 DEBUG_ASSERT(err_data.IsEmpty()); 581 DEBUG_ASSERT(err_data.IsEmpty());
570 582
571 // Calculate the exit code. 583 // Calculate the exit code.
572 intptr_t exit_code = exit_code_data.ints[0]; 584 intptr_t exit_code = exit_code_data.ints[0];
573 intptr_t negative = exit_code_data.ints[1]; 585 intptr_t negative = exit_code_data.ints[1];
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 *os_error_message = DartUtils::ScopedCopyCString( 832 *os_error_message = DartUtils::ScopedCopyCString(
821 "Only ProcessStartMode.NORMAL is supported on this platform"); 833 "Only ProcessStartMode.NORMAL is supported on this platform");
822 return -1; 834 return -1;
823 } 835 }
824 ProcessStarter starter(path, arguments, arguments_length, working_directory, 836 ProcessStarter starter(path, arguments, arguments_length, working_directory,
825 environment, environment_length, mode, in, out, err, 837 environment, environment_length, mode, in, out, err,
826 id, exit_event, os_error_message); 838 id, exit_event, os_error_message);
827 return starter.Start(); 839 return starter.Start();
828 } 840 }
829 841
830
831 intptr_t Process::SetSignalHandler(intptr_t signal) { 842 intptr_t Process::SetSignalHandler(intptr_t signal) {
832 errno = ENOSYS; 843 errno = ENOSYS;
833 return -1; 844 return -1;
834 } 845 }
835 846
836 847 void Process::ClearSignalHandler(intptr_t signal) {}
837 void Process::ClearSignalHandler(intptr_t signal) {
838 }
839 848
840 } // namespace bin 849 } // namespace bin
841 } // namespace dart 850 } // namespace dart
842 851
843 #endif // defined(HOST_OS_FUCHSIA) 852 #endif // defined(HOST_OS_FUCHSIA)
844 853
845 #endif // !defined(DART_IO_DISABLED) 854 #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