Skip to content

Commit add315c

Browse files
committed
[lldb] Updated lldb-server to spawn the child process and share socket on Windows
`lldb-server platform --server` works on Windows now w/o multithreading. The rest functionality remains unchanged. Added also PipeWindows::WriteWithTimeout(), fixed PipeWindows::ReadWithTimeout() and missing initialization of m_read_overlapped.hEvent in the constructor PipeWindows(lldb::pipe_t read, lldb::pipe_t write). Fixes llvm#90923, fixes llvm#56346. Depends on llvm#101326. This is the part 1 of the replacement of llvm#100670. In the part 2 I plan to switch `lldb-server gdbserver` to use `--fd` and listen a common gdb port for all gdbserver connections. Then we can remove gdb port mapping to fix llvm#97537.
1 parent c35c4c7 commit add315c

File tree

3 files changed

+370
-49
lines changed

3 files changed

+370
-49
lines changed

Diff for: lldb/include/lldb/Host/windows/PipeWindows.h

+3
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ class PipeWindows : public PipeBase {
6161
Status Delete(llvm::StringRef name) override;
6262

6363
Status Write(const void *buf, size_t size, size_t &bytes_written) override;
64+
Status WriteWithTimeout(const void *buf, size_t size,
65+
const std::chrono::microseconds &timeout,
66+
size_t &bytes_written);
6467
Status ReadWithTimeout(void *buf, size_t size,
6568
const std::chrono::microseconds &timeout,
6669
size_t &bytes_read) override;

Diff for: lldb/source/Host/windows/PipeWindows.cpp

+61-8
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ PipeWindows::PipeWindows(pipe_t read, pipe_t write)
5858
}
5959

6060
ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
61+
m_read_overlapped.hEvent = ::CreateEventA(nullptr, TRUE, FALSE, nullptr);
62+
6163
ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
64+
m_write_overlapped.hEvent = ::CreateEventA(nullptr, TRUE, FALSE, nullptr);
6265
}
6366

6467
PipeWindows::~PipeWindows() { Close(); }
@@ -77,6 +80,7 @@ Status PipeWindows::CreateNew(bool child_process_inherit) {
7780

7881
m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY);
7982
ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
83+
m_write_overlapped.hEvent = ::CreateEventA(nullptr, TRUE, FALSE, nullptr);
8084

8185
return Status();
8286
}
@@ -202,6 +206,7 @@ Status PipeWindows::OpenNamedPipe(llvm::StringRef name,
202206
m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY);
203207

204208
ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
209+
m_write_overlapped.hEvent = ::CreateEventA(nullptr, TRUE, FALSE, nullptr);
205210
}
206211

207212
return Status();
@@ -228,6 +233,8 @@ int PipeWindows::ReleaseWriteFileDescriptor() {
228233
return PipeWindows::kInvalidDescriptor;
229234
int result = m_write_fd;
230235
m_write_fd = PipeWindows::kInvalidDescriptor;
236+
if (m_write_overlapped.hEvent)
237+
::CloseHandle(m_write_overlapped.hEvent);
231238
m_write = INVALID_HANDLE_VALUE;
232239
ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
233240
return result;
@@ -250,6 +257,9 @@ void PipeWindows::CloseWriteFileDescriptor() {
250257
if (!CanWrite())
251258
return;
252259

260+
if (m_write_overlapped.hEvent)
261+
::CloseHandle(m_write_overlapped.hEvent);
262+
253263
_close(m_write_fd);
254264
m_write = INVALID_HANDLE_VALUE;
255265
m_write_fd = PipeWindows::kInvalidDescriptor;
@@ -283,7 +293,12 @@ Status PipeWindows::ReadWithTimeout(void *buf, size_t size,
283293
DWORD sys_bytes_read = size;
284294
BOOL result = ::ReadFile(m_read, buf, sys_bytes_read, &sys_bytes_read,
285295
&m_read_overlapped);
286-
if (!result && GetLastError() != ERROR_IO_PENDING)
296+
if (result) {
297+
bytes_read = sys_bytes_read;
298+
return Status();
299+
}
300+
301+
if (GetLastError() != ERROR_IO_PENDING)
287302
return Status(::GetLastError(), eErrorTypeWin32);
288303

289304
DWORD timeout = (duration == std::chrono::microseconds::zero())
@@ -319,18 +334,56 @@ Status PipeWindows::ReadWithTimeout(void *buf, size_t size,
319334

320335
Status PipeWindows::Write(const void *buf, size_t num_bytes,
321336
size_t &bytes_written) {
337+
return WriteWithTimeout(buf, num_bytes, std::chrono::microseconds::zero(),
338+
bytes_written);
339+
}
340+
341+
Status PipeWindows::WriteWithTimeout(const void *buf, size_t size,
342+
const std::chrono::microseconds &duration,
343+
size_t &bytes_written) {
322344
if (!CanWrite())
323345
return Status(ERROR_INVALID_HANDLE, eErrorTypeWin32);
324346

325-
DWORD sys_bytes_written = 0;
326-
BOOL write_result = ::WriteFile(m_write, buf, num_bytes, &sys_bytes_written,
327-
&m_write_overlapped);
328-
if (!write_result && GetLastError() != ERROR_IO_PENDING)
347+
bytes_written = 0;
348+
DWORD sys_bytes_write = size;
349+
BOOL result = ::WriteFile(m_write, buf, sys_bytes_write, &sys_bytes_write,
350+
&m_write_overlapped);
351+
if (result) {
352+
bytes_written = sys_bytes_write;
353+
return Status();
354+
}
355+
356+
if (GetLastError() != ERROR_IO_PENDING)
329357
return Status(::GetLastError(), eErrorTypeWin32);
330358

331-
BOOL result = GetOverlappedResult(m_write, &m_write_overlapped,
332-
&sys_bytes_written, TRUE);
333-
if (!result)
359+
DWORD timeout = (duration == std::chrono::microseconds::zero())
360+
? INFINITE
361+
: duration.count() * 1000;
362+
DWORD wait_result = ::WaitForSingleObject(m_write_overlapped.hEvent, timeout);
363+
if (wait_result != WAIT_OBJECT_0) {
364+
// The operation probably failed. However, if it timed out, we need to
365+
// cancel the I/O. Between the time we returned from WaitForSingleObject
366+
// and the time we call CancelIoEx, the operation may complete. If that
367+
// hapens, CancelIoEx will fail and return ERROR_NOT_FOUND. If that
368+
// happens, the original operation should be considered to have been
369+
// successful.
370+
bool failed = true;
371+
DWORD failure_error = ::GetLastError();
372+
if (wait_result == WAIT_TIMEOUT) {
373+
BOOL cancel_result = CancelIoEx(m_write, &m_write_overlapped);
374+
if (!cancel_result && GetLastError() == ERROR_NOT_FOUND)
375+
failed = false;
376+
}
377+
if (failed)
378+
return Status(failure_error, eErrorTypeWin32);
379+
}
380+
381+
// Now we call GetOverlappedResult setting bWait to false, since we've
382+
// already waited as long as we're willing to.
383+
if (!GetOverlappedResult(m_write, &m_write_overlapped, &sys_bytes_write,
384+
FALSE))
334385
return Status(::GetLastError(), eErrorTypeWin32);
386+
387+
bytes_written = sys_bytes_write;
335388
return Status();
336389
}

0 commit comments

Comments
 (0)