diff options
author | Pavel Labath <labath@google.com> | 2015-07-21 09:23:34 +0000 |
---|---|---|
committer | Pavel Labath <labath@google.com> | 2015-07-21 09:23:34 +0000 |
commit | 9f0701f8cafd50bbe9b36795c4331f3d82ce109a (patch) | |
tree | 017bcb9a0539c0118a026502c3da864e3de4407d /lldb/source/Host/windows/PipeWindows.cpp | |
parent | d818e38ff979c21577abada60057c83946852aeb (diff) | |
download | bcm5719-llvm-9f0701f8cafd50bbe9b36795c4331f3d82ce109a.tar.gz bcm5719-llvm-9f0701f8cafd50bbe9b36795c4331f3d82ce109a.zip |
Add Pipe::WriteWithTimeout method
Summary:
This commit adds a WriteWithTimeout method to time Pipe class, analogous to the existing
ReadWithTimeout(). It also changes the meaning of passing zero as a timeout value. Previously,
zero was used as an infinite timeout value. Now, the meaning of zero timeout to return the data
avaiable without sleeping (basically, a non-blocking operation). This makes the behaviour of Pipe
consistent with the Communication/Connection classes. For blocking operatios with infinite
timeout, I introduce a special constant for this purpose.
Reviewers: ovyalov, zturner
Subscribers: lldb-commits
Differential Revision: http://reviews.llvm.org/D11358
llvm-svn: 242764
Diffstat (limited to 'lldb/source/Host/windows/PipeWindows.cpp')
-rw-r--r-- | lldb/source/Host/windows/PipeWindows.cpp | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/lldb/source/Host/windows/PipeWindows.cpp b/lldb/source/Host/windows/PipeWindows.cpp index d4afd6e7494..e2029971742 100644 --- a/lldb/source/Host/windows/PipeWindows.cpp +++ b/lldb/source/Host/windows/PipeWindows.cpp @@ -289,7 +289,7 @@ PipeWindows::ReadWithTimeout(void *buf, size_t size, const std::chrono::microsec if (!result && GetLastError() != ERROR_IO_PENDING) return Error(::GetLastError(), eErrorTypeWin32); - DWORD timeout = (duration == std::chrono::microseconds::zero()) ? INFINITE : duration.count() * 1000; + DWORD timeout = (duration == kInfiniteTimeout) ? INFINITE : duration.count() * 1000; DWORD wait_result = ::WaitForSingleObject(m_read_overlapped.hEvent, timeout); if (wait_result != WAIT_OBJECT_0) { @@ -319,7 +319,10 @@ PipeWindows::ReadWithTimeout(void *buf, size_t size, const std::chrono::microsec } Error -PipeWindows::Write(const void *buf, size_t num_bytes, size_t &bytes_written) +PipeWindows::WriteWithTimeout(const void *buf, + size_t num_bytes, + const std::chrono::microseconds &duration, + size_t &bytes_written) { if (!CanWrite()) return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32); @@ -329,8 +332,32 @@ PipeWindows::Write(const void *buf, size_t num_bytes, size_t &bytes_written) if (!write_result && GetLastError() != ERROR_IO_PENDING) return Error(::GetLastError(), eErrorTypeWin32); - BOOL result = GetOverlappedResult(m_write, &m_write_overlapped, &sys_bytes_written, TRUE); + DWORD timeout = (duration == kInfiniteTimeout) ? INFINITE : duration.count() * 1000; + DWORD wait_result = ::WaitForSingleObject(m_write_overlapped.hEvent, timeout); + if (wait_result != WAIT_OBJECT_0) + { + // The operation probably failed. However, if it timed out, we need to cancel the I/O. + // Between the time we returned from WaitForSingleObject and the time we call CancelIoEx, + // the operation may complete. If that hapens, CancelIoEx will fail and return ERROR_NOT_FOUND. + // If that happens, the original operation should be considered to have been successful. + bool failed = true; + DWORD failure_error = ::GetLastError(); + if (wait_result == WAIT_TIMEOUT) + { + BOOL cancel_result = CancelIoEx(m_read, &m_write_overlapped); + if (!cancel_result && GetLastError() == ERROR_NOT_FOUND) + failed = false; + } + if (failed) + return Error(failure_error, eErrorTypeWin32); + } + + // Now we call GetOverlappedResult setting bWait to false, since we've already waited + // as long as we're willing to. + BOOL result = GetOverlappedResult(m_write, &m_write_overlapped, &sys_bytes_written, FALSE); if (!result) return Error(::GetLastError(), eErrorTypeWin32); + + bytes_written = sys_bytes_written; return Error(); } |