Chromium Code Reviews| Index: runtime/bin/process_linux.cc |
| diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc |
| index 6102e704e6c4ed4cfc06ebd7de754a1d70542e21..47564c25145fdd145583b9d9f4317245e0aa1a20 100644 |
| --- a/runtime/bin/process_linux.cc |
| +++ b/runtime/bin/process_linux.cc |
| @@ -568,6 +568,122 @@ 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; |
| +} |
| + |
| + |
| +static bool CloseProcessBuffers(struct pollfd fds[3]) { |
| + int e = errno; |
| + VOID_TEMP_FAILURE_RETRY(close(fds[0].fd)); |
| + VOID_TEMP_FAILURE_RETRY(close(fds[1].fd)); |
| + VOID_TEMP_FAILURE_RETRY(close(fds[2].fd)); |
| + errno = e; |
| + return false; |
| +} |
| + |
| + |
| +bool Process::Wait(intptr_t pid, |
| + intptr_t in, |
| + intptr_t out, |
| + intptr_t err, |
| + intptr_t exit_event, |
| + ProcessResult* result) { |
| + // 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; |
| + union { |
| + uint8_t bytes[8]; |
| + int32_t ints[2]; |
| + } exit_code_data; |
| + |
| + struct pollfd fds[3]; |
| + fds[0].fd = out; |
| + fds[1].fd = err; |
| + fds[2].fd = exit_event; |
| + |
| + for (int i = 0; i < 3; i++) { |
| + fds[i].events = POLLIN; |
| + } |
| + |
| + int alive = 3; |
| + while (alive > 0) { |
| + if (TEMP_FAILURE_RETRY(poll(fds, alive, -1)) <= 0) { |
|
Bill Hesse
2013/08/09 15:32:23
Add comment - blocking call. This implements a Da
Søren Gjesse
2013/08/12 06:52:38
Done.
|
| + return CloseProcessBuffers(fds); |
| + } |
| + for (int i = 0; i < alive; i++) { |
| + if (fds[i].revents & POLLIN) { |
| + intptr_t avail = FDUtils::AvailableBytes(fds[i].fd); |
| + if (fds[i].fd == out) { |
| + if (!ReadProcessBuffer(&out_data, &out_data_length, avail, out)) { |
| + return CloseProcessBuffers(fds); |
| + } |
| + } else if (fds[i].fd == err) { |
| + if (!ReadProcessBuffer(&err_data, &err_data_length, avail, err)) { |
| + return CloseProcessBuffers(fds); |
| + } |
| + } else if (fds[i].fd == exit_event) { |
| + intptr_t avail = FDUtils::AvailableBytes(fds[i].fd); |
| + if (avail == 8) { |
| + intptr_t bytes = 0; |
| + do { |
| + intptr_t b = TEMP_FAILURE_RETRY(read(fds[i].fd, |
| + exit_code_data.bytes, 8)); |
|
Bill Hesse
2013/08/09 15:32:23
shouldn't this be read(fds[i].fd, exit_code_data.b
Søren Gjesse
2013/08/12 06:52:38
Removed the while, as we know that there are 8 byt
|
| + if (b > 0) { |
| + bytes += b; |
| + } else { |
| + return CloseProcessBuffers(fds); |
| + } |
| + } while (bytes < 8); |
| + } |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + continue; |
| + } |
| + |
| + if (fds[i].revents & POLLHUP) { |
| + VOID_TEMP_FAILURE_RETRY(close(fds[i].fd)); |
| + alive--; |
| + if (i < alive) { |
|
Bill Hesse
2013/08/09 15:32:23
This guard is not really needed. But it is OK, si
Søren Gjesse
2013/08/12 06:52:38
This is needed as calling poll with closed file de
|
| + fds[i] = fds[alive]; |
| + } |
| + } |
| + } |
| + } |
| + |
| + // All handles closed and all data read. |
| + result->SetStdoutData(out_data, out_data_length); |
| + result->SetStderrData(err_data, err_data_length); |
| + |
| + // Calculate the exit code. |
| + intptr_t exit_code = exit_code_data.ints[0]; |
| + intptr_t negative = exit_code_data.ints[1]; |
| + if (negative) exit_code = -exit_code; |
| + result->set_exit_code(exit_code); |
| + |
| + return true; |
| +} |
| + |
| + |
| bool Process::Kill(intptr_t id, int signal) { |
| return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1); |
| } |