Skip to content

Commit

Permalink
[lldb] Updated lldb-server to spawn the child process and share socke…
Browse files Browse the repository at this point in the history
…t 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.
  • Loading branch information
slydiman committed Jul 31, 2024
1 parent c35c4c7 commit add315c
Show file tree
Hide file tree
Showing 3 changed files with 370 additions and 49 deletions.
3 changes: 3 additions & 0 deletions lldb/include/lldb/Host/windows/PipeWindows.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ class PipeWindows : public PipeBase {
Status Delete(llvm::StringRef name) override;

Status Write(const void *buf, size_t size, size_t &bytes_written) override;
Status WriteWithTimeout(const void *buf, size_t size,
const std::chrono::microseconds &timeout,
size_t &bytes_written);
Status ReadWithTimeout(void *buf, size_t size,
const std::chrono::microseconds &timeout,
size_t &bytes_read) override;
Expand Down
69 changes: 61 additions & 8 deletions lldb/source/Host/windows/PipeWindows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ PipeWindows::PipeWindows(pipe_t read, pipe_t write)
}

ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
m_read_overlapped.hEvent = ::CreateEventA(nullptr, TRUE, FALSE, nullptr);

ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
m_write_overlapped.hEvent = ::CreateEventA(nullptr, TRUE, FALSE, nullptr);
}

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

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

return Status();
}
Expand Down Expand Up @@ -202,6 +206,7 @@ Status PipeWindows::OpenNamedPipe(llvm::StringRef name,
m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY);

ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
m_write_overlapped.hEvent = ::CreateEventA(nullptr, TRUE, FALSE, nullptr);
}

return Status();
Expand All @@ -228,6 +233,8 @@ int PipeWindows::ReleaseWriteFileDescriptor() {
return PipeWindows::kInvalidDescriptor;
int result = m_write_fd;
m_write_fd = PipeWindows::kInvalidDescriptor;
if (m_write_overlapped.hEvent)
::CloseHandle(m_write_overlapped.hEvent);
m_write = INVALID_HANDLE_VALUE;
ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
return result;
Expand All @@ -250,6 +257,9 @@ void PipeWindows::CloseWriteFileDescriptor() {
if (!CanWrite())
return;

if (m_write_overlapped.hEvent)
::CloseHandle(m_write_overlapped.hEvent);

_close(m_write_fd);
m_write = INVALID_HANDLE_VALUE;
m_write_fd = PipeWindows::kInvalidDescriptor;
Expand Down Expand Up @@ -283,7 +293,12 @@ Status PipeWindows::ReadWithTimeout(void *buf, size_t size,
DWORD sys_bytes_read = size;
BOOL result = ::ReadFile(m_read, buf, sys_bytes_read, &sys_bytes_read,
&m_read_overlapped);
if (!result && GetLastError() != ERROR_IO_PENDING)
if (result) {
bytes_read = sys_bytes_read;
return Status();
}

if (GetLastError() != ERROR_IO_PENDING)
return Status(::GetLastError(), eErrorTypeWin32);

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

Status PipeWindows::Write(const void *buf, size_t num_bytes,
size_t &bytes_written) {
return WriteWithTimeout(buf, num_bytes, std::chrono::microseconds::zero(),
bytes_written);
}

Status PipeWindows::WriteWithTimeout(const void *buf, size_t size,
const std::chrono::microseconds &duration,
size_t &bytes_written) {
if (!CanWrite())
return Status(ERROR_INVALID_HANDLE, eErrorTypeWin32);

DWORD sys_bytes_written = 0;
BOOL write_result = ::WriteFile(m_write, buf, num_bytes, &sys_bytes_written,
&m_write_overlapped);
if (!write_result && GetLastError() != ERROR_IO_PENDING)
bytes_written = 0;
DWORD sys_bytes_write = size;
BOOL result = ::WriteFile(m_write, buf, sys_bytes_write, &sys_bytes_write,
&m_write_overlapped);
if (result) {
bytes_written = sys_bytes_write;
return Status();
}

if (GetLastError() != ERROR_IO_PENDING)
return Status(::GetLastError(), eErrorTypeWin32);

BOOL result = GetOverlappedResult(m_write, &m_write_overlapped,
&sys_bytes_written, TRUE);
if (!result)
DWORD timeout = (duration == std::chrono::microseconds::zero())
? 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_write, &m_write_overlapped);
if (!cancel_result && GetLastError() == ERROR_NOT_FOUND)
failed = false;
}
if (failed)
return Status(failure_error, eErrorTypeWin32);
}

// Now we call GetOverlappedResult setting bWait to false, since we've
// already waited as long as we're willing to.
if (!GetOverlappedResult(m_write, &m_write_overlapped, &sys_bytes_write,
FALSE))
return Status(::GetLastError(), eErrorTypeWin32);

bytes_written = sys_bytes_write;
return Status();
}
Loading

0 comments on commit add315c

Please sign in to comment.