| Index: runtime/bin/process_macos.cc
|
| diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
|
| index 8187026f5655c64d5e82e2fdc13e48ce006e084e..23de1fd525dfce66301f21d56869725aff2db445 100644
|
| --- a/runtime/bin/process_macos.cc
|
| +++ b/runtime/bin/process_macos.cc
|
| @@ -567,23 +567,27 @@ int Process::Start(const char* path,
|
| }
|
|
|
|
|
| -static bool ReadProcessBuffer(uint8_t** buffer,
|
| - intptr_t* buffer_length,
|
| - intptr_t available,
|
| - int fd) {
|
| - uint8_t* tmp = new uint8_t[*buffer_length + available];
|
| - if (tmp == NULL) FATAL("Allocation failed");
|
| - memmove(tmp, *buffer, *buffer_length);
|
| - delete[] *buffer;
|
| - *buffer = tmp;
|
| - intptr_t bytes = TEMP_FAILURE_RETRY(read(
|
| - fd,
|
| - reinterpret_cast<void*>(*buffer + *buffer_length),
|
| - available));
|
| - if (bytes < 0) return false;
|
| - *buffer_length += bytes;
|
| - return true;
|
| -}
|
| +class BufferList: public BufferListBase {
|
| + public:
|
| + bool Read(int fd, intptr_t available) {
|
| + // Read all available bytes.
|
| + while (available > 0) {
|
| + if (free_size_ == 0) Allocate();
|
| + ASSERT(free_size_ > 0);
|
| + ASSERT(free_size_ <= kBufferSize);
|
| + intptr_t block_size = dart::Utils::Minimum(free_size_, available);
|
| + intptr_t bytes = TEMP_FAILURE_RETRY(read(
|
| + fd,
|
| + reinterpret_cast<void*>(tail_->data_ + (kBufferSize - free_size_)),
|
| + block_size));
|
| + if (bytes < 0) return false;
|
| + data_size_ += bytes;
|
| + free_size_ -= bytes;
|
| + available -= bytes;
|
| + }
|
| + return true;
|
| + }
|
| +};
|
|
|
|
|
| static bool CloseProcessBuffers(struct pollfd fds[3]) {
|
| @@ -605,10 +609,11 @@ bool Process::Wait(intptr_t pid,
|
| // Close input to the process right away.
|
| VOID_TEMP_FAILURE_RETRY(close(in));
|
|
|
| - uint8_t* out_data = NULL;
|
| - intptr_t out_data_length = 0;
|
| - uint8_t* err_data = NULL;
|
| - intptr_t err_data_length = 0;
|
| + // There is no return from this function using Dart_PropagateError
|
| + // as memory used by the buffer lists is freed through their
|
| + // destructors.
|
| + BufferList out_data;
|
| + BufferList err_data;
|
| union {
|
| uint8_t bytes[8];
|
| int32_t ints[2];
|
| @@ -629,6 +634,8 @@ bool Process::Wait(intptr_t pid,
|
| if (TEMP_FAILURE_RETRY(poll(fds, alive, -1)) <= 0) {
|
| return CloseProcessBuffers(fds);
|
| }
|
| +
|
| + // Process incoming data.
|
| for (int i = 0; i < alive; i++) {
|
| if (fds[i].revents & POLLIN) {
|
| intptr_t avail = FDUtils::AvailableBytes(fds[i].fd);
|
| @@ -636,15 +643,14 @@ bool Process::Wait(intptr_t pid,
|
| // bytes. POLLHUP is most likely also set in this case.
|
| if (avail > 0) {
|
| if (fds[i].fd == out) {
|
| - if (!ReadProcessBuffer(&out_data, &out_data_length, avail, out)) {
|
| + if (!out_data.Read(out, avail)) {
|
| return CloseProcessBuffers(fds);
|
| }
|
| } else if (fds[i].fd == err) {
|
| - if (!ReadProcessBuffer(&err_data, &err_data_length, avail, err)) {
|
| + if (!err_data.Read(err, avail)) {
|
| return CloseProcessBuffers(fds);
|
| }
|
| } else if (fds[i].fd == exit_event) {
|
| - intptr_t avail = FDUtils::AvailableBytes(fds[i].fd);
|
| if (avail == 8) {
|
| intptr_t b = TEMP_FAILURE_RETRY(read(fds[i].fd,
|
| exit_code_data.bytes, 8));
|
| @@ -655,10 +661,12 @@ bool Process::Wait(intptr_t pid,
|
| } else {
|
| UNREACHABLE();
|
| }
|
| - continue;
|
| }
|
| }
|
| + }
|
|
|
| + // Process closed.
|
| + for (int i = 0; i < alive; i++) {
|
| if (fds[i].revents & POLLHUP) {
|
| VOID_TEMP_FAILURE_RETRY(close(fds[i].fd));
|
| alive--;
|
| @@ -670,8 +678,8 @@ bool Process::Wait(intptr_t pid,
|
| }
|
|
|
| // All handles closed and all data read.
|
| - result->SetStdoutData(out_data, out_data_length);
|
| - result->SetStderrData(err_data, err_data_length);
|
| + result->set_stdout_data(out_data.GetData());
|
| + result->set_stderr_data(err_data.GetData());
|
|
|
| // Calculate the exit code.
|
| intptr_t exit_code = exit_code_data.ints[0];
|
|
|