17
17
#include < magenta/status.h>
18
18
#include < magenta/syscalls.h>
19
19
#include < magenta/syscalls/object.h>
20
+ #include < magenta/types.h>
21
+ #include < mxio/private.h>
20
22
#include < mxio/util.h>
21
23
#include < pthread.h>
22
24
#include < stdbool.h>
@@ -454,18 +456,56 @@ int64_t Process::MaxRSS() {
454
456
455
457
static bool ProcessWaitCleanup (intptr_t out,
456
458
intptr_t err,
457
- intptr_t exit_event,
458
- intptr_t epoll_fd) {
459
+ intptr_t exit_event) {
459
460
int e = errno;
460
461
VOID_NO_RETRY_EXPECTED (close (out));
461
462
VOID_NO_RETRY_EXPECTED (close (err));
462
463
VOID_NO_RETRY_EXPECTED (close (exit_event));
463
- VOID_NO_RETRY_EXPECTED (close (epoll_fd));
464
464
errno = e;
465
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
509
bool Process::Wait (intptr_t pid,
470
510
intptr_t in,
471
511
intptr_t out,
@@ -484,83 +524,55 @@ bool Process::Wait(intptr_t pid,
484
524
int32_t ints[2 ];
485
525
} exit_code_data;
486
526
487
- // The initial size passed to epoll_create is ignore on newer (>=
488
- // 2.6.8) Linux versions
489
- static const int kEpollInitialSize = 64 ;
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
- }
527
+ constexpr size_t kWaitItemsCount = 3 ;
528
+ uint32_t events[kWaitItemsCount ];
529
+ mx_wait_item_t wait_items[kWaitItemsCount ];
530
+ size_t active = kWaitItemsCount ;
497
531
498
- struct epoll_event event;
499
- event.events = EPOLLRDHUP | EPOLLIN;
500
- event.data .fd = out;
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 ;
532
+ MxioWaitEntry entries[kWaitItemsCount ];
533
+ entries[0 ].Init (out);
534
+ entries[1 ].Init (err);
535
+ entries[2 ].Init (exit_event);
519
536
520
- static const intptr_t kMaxEvents = 16 ;
521
- struct epoll_event events[kMaxEvents ];
522
537
while (active > 0 ) {
523
- // TODO(US-109): When the epoll implementation is properly edge-triggered,
524
- // remove this sleep, which prevents the message queue from being
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
- }
532
- for (intptr_t i = 0 ; i < result; i++) {
533
- if ((events[i].events & EPOLLIN) != 0 ) {
534
- const intptr_t avail = FDUtils::AvailableBytes (events[i].data .fd );
535
- if (events[i].data .fd == out) {
536
- if (!out_data.Read (out, avail)) {
537
- return ProcessWaitCleanup (out, err, exit_event, epoll_fd);
538
- }
539
- } else if (events[i].data .fd == err) {
540
- if (!err_data.Read (err, avail)) {
541
- return ProcessWaitCleanup (out, err, exit_event, epoll_fd);
542
- }
543
- } else if (events[i].data .fd == exit_event) {
544
- if (avail == 8 ) {
545
- intptr_t b =
546
- NO_RETRY_EXPECTED (read (exit_event, exit_code_data.bytes , 8 ));
547
- if (b != 8 ) {
548
- return ProcessWaitCleanup (out, err, exit_event, epoll_fd);
549
- }
550
- }
551
- } else {
552
- UNREACHABLE ();
538
+ for (size_t i = 0 ; i < kWaitItemsCount ; ++i) {
539
+ entries[i].WaitBegin (&wait_items[i]);
540
+ }
541
+ mx_object_wait_many (wait_items, kWaitItemsCount , MX_TIME_INFINITE);
542
+
543
+ for (size_t i = 0 ; i < kWaitItemsCount ; ++i) {
544
+ entries[i].WaitEnd (&wait_items[i], &events[i]);
545
+ }
546
+
547
+ if ((events[0 ] & EPOLLIN) != 0 ) {
548
+ const intptr_t avail = FDUtils::AvailableBytes (out);
549
+ if (!out_data.Read (out, avail)) {
550
+ return ProcessWaitCleanup (out, err, exit_event);
551
+ }
552
+ }
553
+ if ((events[1 ] & EPOLLIN) != 0 ) {
554
+ const intptr_t avail = FDUtils::AvailableBytes (err);
555
+ if (!err_data.Read (err, avail)) {
556
+ return ProcessWaitCleanup (out, err, exit_event);
557
+ }
558
+ }
559
+ if ((events[2 ] & EPOLLIN) != 0 ) {
560
+ const intptr_t avail = FDUtils::AvailableBytes (exit_event);
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 ) {
556
- NO_RETRY_EXPECTED (close (events[i].data .fd ));
568
+ }
569
+ for (size_t i = 0 ; i < kWaitItemsCount ; ++i) {
570
+ if ((events[i] & EPOLLRDHUP) != 0 ) {
557
571
active--;
558
- VOID_NO_RETRY_EXPECTED (
559
- epoll_ctl (epoll_fd, EPOLL_CTL_DEL, events[i].data .fd , NULL ));
572
+ entries[i].Cancel ();
560
573
}
561
574
}
562
575
}
563
- VOID_NO_RETRY_EXPECTED (close (epoll_fd));
564
576
565
577
// All handles closed and all data read.
566
578
result->set_stdout_data (out_data.GetData ());
@@ -827,15 +839,12 @@ int Process::Start(const char* path,
827
839
return starter.Start ();
828
840
}
829
841
830
-
831
842
intptr_t Process::SetSignalHandler (intptr_t signal) {
832
843
errno = ENOSYS;
833
844
return -1 ;
834
845
}
835
846
836
-
837
- void Process::ClearSignalHandler (intptr_t signal) {
838
- }
847
+ void Process::ClearSignalHandler (intptr_t signal) {}
839
848
840
849
} // namespace bin
841
850
} // namespace dart
0 commit comments