Index: runtime/bin/process_fuchsia.cc |
diff --git a/runtime/bin/process_fuchsia.cc b/runtime/bin/process_fuchsia.cc |
index 62740869af1d6eba026c10042e384a9163efec34..93f4d34fd78ea6aedb887e19eb11438584f2dee5 100644 |
--- a/runtime/bin/process_fuchsia.cc |
+++ b/runtime/bin/process_fuchsia.cc |
@@ -17,6 +17,8 @@ |
#include <magenta/status.h> |
#include <magenta/syscalls.h> |
#include <magenta/syscalls/object.h> |
+#include <magenta/types.h> |
+#include <mxio/private.h> |
#include <mxio/util.h> |
#include <pthread.h> |
#include <stdbool.h> |
@@ -454,18 +456,56 @@ int64_t Process::MaxRSS() { |
static bool ProcessWaitCleanup(intptr_t out, |
intptr_t err, |
- intptr_t exit_event, |
- intptr_t epoll_fd) { |
+ intptr_t exit_event) { |
int e = errno; |
VOID_NO_RETRY_EXPECTED(close(out)); |
VOID_NO_RETRY_EXPECTED(close(err)); |
VOID_NO_RETRY_EXPECTED(close(exit_event)); |
- VOID_NO_RETRY_EXPECTED(close(epoll_fd)); |
errno = e; |
return false; |
} |
+class MxioWaitEntry { |
+ public: |
+ MxioWaitEntry() {} |
+ ~MxioWaitEntry() { Cancel(); } |
+ |
+ void Init(int fd) { mxio_ = __mxio_fd_to_io(fd); } |
+ |
+ void WaitBegin(mx_wait_item_t* wait_item) { |
+ if (mxio_ == NULL) { |
+ *wait_item = {}; |
+ return; |
+ } |
+ |
+ __mxio_wait_begin(mxio_, EPOLLRDHUP | EPOLLIN, &wait_item->handle, |
+ &wait_item->waitfor); |
+ wait_item->pending = 0; |
+ } |
+ |
+ void WaitEnd(mx_wait_item_t* wait_item, uint32_t* event) { |
+ if (mxio_ == NULL) { |
+ *event = 0; |
+ return; |
+ } |
+ __mxio_wait_end(mxio_, wait_item->pending, event); |
+ } |
+ |
+ void Cancel() { |
+ if (mxio_ != NULL) { |
+ __mxio_release(mxio_); |
+ } |
+ mxio_ = NULL; |
+ } |
+ |
+ private: |
+ mxio_t* mxio_ = NULL; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MxioWaitEntry); |
+}; |
+ |
+ |
bool Process::Wait(intptr_t pid, |
intptr_t in, |
intptr_t out, |
@@ -484,83 +524,55 @@ bool Process::Wait(intptr_t pid, |
int32_t ints[2]; |
} exit_code_data; |
- // The initial size passed to epoll_create is ignore on newer (>= |
- // 2.6.8) Linux versions |
- static const int kEpollInitialSize = 64; |
- int epoll_fd = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize)); |
- if (epoll_fd == -1) { |
- return ProcessWaitCleanup(out, err, exit_event, epoll_fd); |
- } |
- if (!FDUtils::SetCloseOnExec(epoll_fd)) { |
- return ProcessWaitCleanup(out, err, exit_event, epoll_fd); |
- } |
+ constexpr size_t kWaitItemsCount = 3; |
+ uint32_t events[kWaitItemsCount]; |
+ mx_wait_item_t wait_items[kWaitItemsCount]; |
+ size_t active = kWaitItemsCount; |
- struct epoll_event event; |
- event.events = EPOLLRDHUP | EPOLLIN; |
- event.data.fd = out; |
- int status = NO_RETRY_EXPECTED( |
- epoll_ctl(epoll_fd, EPOLL_CTL_ADD, out, &event)); |
- if (status == -1) { |
- return ProcessWaitCleanup(out, err, exit_event, epoll_fd); |
- } |
- event.data.fd = err; |
- status = NO_RETRY_EXPECTED( |
- epoll_ctl(epoll_fd, EPOLL_CTL_ADD, err, &event)); |
- if (status == -1) { |
- return ProcessWaitCleanup(out, err, exit_event, epoll_fd); |
- } |
- event.data.fd = exit_event; |
- status = NO_RETRY_EXPECTED( |
- epoll_ctl(epoll_fd, EPOLL_CTL_ADD, exit_event, &event)); |
- if (status == -1) { |
- return ProcessWaitCleanup(out, err, exit_event, epoll_fd); |
- } |
- intptr_t active = 3; |
+ MxioWaitEntry entries[kWaitItemsCount]; |
+ entries[0].Init(out); |
+ entries[1].Init(err); |
+ entries[2].Init(exit_event); |
- static const intptr_t kMaxEvents = 16; |
- struct epoll_event events[kMaxEvents]; |
while (active > 0) { |
- // TODO(US-109): When the epoll implementation is properly edge-triggered, |
- // remove this sleep, which prevents the message queue from being |
- // overwhelmed and leading to memory exhaustion. |
- usleep(5000); |
- intptr_t result = NO_RETRY_EXPECTED( |
- epoll_wait(epoll_fd, events, kMaxEvents, -1)); |
- if ((result < 0) && (errno != EWOULDBLOCK)) { |
- return ProcessWaitCleanup(out, err, exit_event, epoll_fd); |
- } |
- for (intptr_t i = 0; i < result; i++) { |
- if ((events[i].events & EPOLLIN) != 0) { |
- const intptr_t avail = FDUtils::AvailableBytes(events[i].data.fd); |
- if (events[i].data.fd == out) { |
- if (!out_data.Read(out, avail)) { |
- return ProcessWaitCleanup(out, err, exit_event, epoll_fd); |
- } |
- } else if (events[i].data.fd == err) { |
- if (!err_data.Read(err, avail)) { |
- return ProcessWaitCleanup(out, err, exit_event, epoll_fd); |
- } |
- } else if (events[i].data.fd == exit_event) { |
- if (avail == 8) { |
- intptr_t b = |
- NO_RETRY_EXPECTED(read(exit_event, exit_code_data.bytes, 8)); |
- if (b != 8) { |
- return ProcessWaitCleanup(out, err, exit_event, epoll_fd); |
- } |
- } |
- } else { |
- UNREACHABLE(); |
+ for (size_t i = 0; i < kWaitItemsCount; ++i) { |
+ entries[i].WaitBegin(&wait_items[i]); |
+ } |
+ mx_object_wait_many(wait_items, kWaitItemsCount, MX_TIME_INFINITE); |
+ |
+ for (size_t i = 0; i < kWaitItemsCount; ++i) { |
+ entries[i].WaitEnd(&wait_items[i], &events[i]); |
+ } |
+ |
+ if ((events[0] & EPOLLIN) != 0) { |
+ const intptr_t avail = FDUtils::AvailableBytes(out); |
+ if (!out_data.Read(out, avail)) { |
+ return ProcessWaitCleanup(out, err, exit_event); |
+ } |
+ } |
+ if ((events[1] & EPOLLIN) != 0) { |
+ const intptr_t avail = FDUtils::AvailableBytes(err); |
+ if (!err_data.Read(err, avail)) { |
+ 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!
|
+ } |
+ } |
+ if ((events[2] & EPOLLIN) != 0) { |
+ const intptr_t avail = FDUtils::AvailableBytes(exit_event); |
+ if (avail == 8) { |
+ intptr_t b = |
+ NO_RETRY_EXPECTED(read(exit_event, exit_code_data.bytes, 8)); |
+ if (b != 8) { |
+ return ProcessWaitCleanup(out, err, exit_event); |
} |
} |
- if ((events[i].events & (EPOLLHUP | EPOLLRDHUP)) != 0) { |
- NO_RETRY_EXPECTED(close(events[i].data.fd)); |
+ } |
+ for (size_t i = 0; i < kWaitItemsCount; ++i) { |
+ if ((events[i] & EPOLLRDHUP) != 0) { |
active--; |
- VOID_NO_RETRY_EXPECTED( |
- epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd, NULL)); |
+ entries[i].Cancel(); |
} |
} |
} |
- VOID_NO_RETRY_EXPECTED(close(epoll_fd)); |
// All handles closed and all data read. |
result->set_stdout_data(out_data.GetData()); |
@@ -827,15 +839,12 @@ int Process::Start(const char* path, |
return starter.Start(); |
} |
- |
intptr_t Process::SetSignalHandler(intptr_t signal) { |
errno = ENOSYS; |
return -1; |
} |
- |
-void Process::ClearSignalHandler(intptr_t signal) { |
-} |
+void Process::ClearSignalHandler(intptr_t signal) {} |
} // namespace bin |
} // namespace dart |