Skip to content

Commit 1e24670

Browse files
ashgtiJDevlieghere
andauthored
[lldb-dap] Use existing lldb::IOObjectSP for DAP IO (NFC). (llvm#128750)
This simplifies the IOStream.cpp implementation by building on top of the existing lldb::IOObjectSP. Additionally, this should help ensure clients connected of a `--connection` specifier properly detect shutdown requests when the Socket is closed. Previously, the StreamDescriptor was just accessing the underlying native handle and was not aware of the `Close()` call to the Socket itself. This is both nice to have for simplifying the existing code and this unblocks an upcoming refactor to support the cancel request. --------- Co-authored-by: Jonas Devlieghere <[email protected]>
1 parent cfdeca3 commit 1e24670

File tree

5 files changed

+42
-155
lines changed

5 files changed

+42
-155
lines changed

lldb/tools/lldb-dap/DAP.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "lldb/API/SBListener.h"
1919
#include "lldb/API/SBProcess.h"
2020
#include "lldb/API/SBStream.h"
21+
#include "lldb/Utility/IOObject.h"
2122
#include "lldb/Utility/Status.h"
2223
#include "lldb/lldb-defines.h"
2324
#include "lldb/lldb-enumerations.h"
@@ -61,7 +62,7 @@ const char DEV_NULL[] = "/dev/null";
6162
namespace lldb_dap {
6263

6364
DAP::DAP(std::string name, llvm::StringRef path, std::ofstream *log,
64-
StreamDescriptor input, StreamDescriptor output, ReplMode repl_mode,
65+
lldb::IOObjectSP input, lldb::IOObjectSP output, ReplMode repl_mode,
6566
std::vector<std::string> pre_init_commands)
6667
: name(std::move(name)), debug_adaptor_path(path), log(log),
6768
input(std::move(input)), output(std::move(output)),

lldb/tools/lldb-dap/DAP.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "lldb/API/SBThread.h"
3131
#include "lldb/API/SBValue.h"
3232
#include "lldb/API/SBValueList.h"
33+
#include "lldb/lldb-forward.h"
3334
#include "lldb/lldb-types.h"
3435
#include "llvm/ADT/DenseMap.h"
3536
#include "llvm/ADT/DenseSet.h"
@@ -210,7 +211,7 @@ struct DAP {
210211
std::string last_nonempty_var_expression;
211212

212213
DAP(std::string name, llvm::StringRef path, std::ofstream *log,
213-
StreamDescriptor input, StreamDescriptor output, ReplMode repl_mode,
214+
lldb::IOObjectSP input, lldb::IOObjectSP output, ReplMode repl_mode,
214215
std::vector<std::string> pre_init_commands);
215216
~DAP();
216217
DAP(const DAP &rhs) = delete;

lldb/tools/lldb-dap/IOStream.cpp

Lines changed: 13 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -7,125 +7,34 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "IOStream.h"
10+
#include "lldb/Utility/IOObject.h"
11+
#include "lldb/Utility/Status.h"
1012
#include <fstream>
1113
#include <string>
1214

13-
#if defined(_WIN32)
14-
#include <io.h>
15-
#else
16-
#include <netinet/in.h>
17-
#include <sys/socket.h>
18-
#include <unistd.h>
19-
#endif
20-
2115
using namespace lldb_dap;
2216

23-
StreamDescriptor::StreamDescriptor() = default;
24-
25-
StreamDescriptor::StreamDescriptor(StreamDescriptor &&other) {
26-
*this = std::move(other);
27-
}
28-
29-
StreamDescriptor::~StreamDescriptor() {
30-
if (!m_close)
31-
return;
32-
33-
if (m_is_socket)
34-
#if defined(_WIN32)
35-
::closesocket(m_socket);
36-
#else
37-
::close(m_socket);
38-
#endif
39-
else
40-
::close(m_fd);
41-
}
42-
43-
StreamDescriptor &StreamDescriptor::operator=(StreamDescriptor &&other) {
44-
m_close = other.m_close;
45-
other.m_close = false;
46-
m_is_socket = other.m_is_socket;
47-
if (m_is_socket)
48-
m_socket = other.m_socket;
49-
else
50-
m_fd = other.m_fd;
51-
return *this;
52-
}
53-
54-
StreamDescriptor StreamDescriptor::from_socket(SOCKET s, bool close) {
55-
StreamDescriptor sd;
56-
sd.m_is_socket = true;
57-
sd.m_socket = s;
58-
sd.m_close = close;
59-
return sd;
60-
}
61-
62-
StreamDescriptor StreamDescriptor::from_file(int fd, bool close) {
63-
StreamDescriptor sd;
64-
sd.m_is_socket = false;
65-
sd.m_fd = fd;
66-
sd.m_close = close;
67-
return sd;
68-
}
69-
7017
bool OutputStream::write_full(llvm::StringRef str) {
71-
while (!str.empty()) {
72-
int bytes_written = 0;
73-
if (descriptor.m_is_socket)
74-
bytes_written = ::send(descriptor.m_socket, str.data(), str.size(), 0);
75-
else
76-
bytes_written = ::write(descriptor.m_fd, str.data(), str.size());
77-
78-
if (bytes_written < 0) {
79-
if (errno == EINTR || errno == EAGAIN)
80-
continue;
81-
return false;
82-
}
83-
str = str.drop_front(bytes_written);
84-
}
18+
if (!descriptor)
19+
return false;
8520

86-
return true;
21+
size_t num_bytes = str.size();
22+
auto status = descriptor->Write(str.data(), num_bytes);
23+
return status.Success();
8724
}
8825

8926
bool InputStream::read_full(std::ofstream *log, size_t length,
9027
std::string &text) {
28+
if (!descriptor)
29+
return false;
30+
9131
std::string data;
9232
data.resize(length);
9333

94-
char *ptr = &data[0];
95-
while (length != 0) {
96-
int bytes_read = 0;
97-
if (descriptor.m_is_socket)
98-
bytes_read = ::recv(descriptor.m_socket, ptr, length, 0);
99-
else
100-
bytes_read = ::read(descriptor.m_fd, ptr, length);
101-
102-
if (bytes_read == 0) {
103-
if (log)
104-
*log << "End of file (EOF) reading from input file.\n";
105-
return false;
106-
}
107-
if (bytes_read < 0) {
108-
int reason = 0;
109-
#if defined(_WIN32)
110-
if (descriptor.m_is_socket)
111-
reason = WSAGetLastError();
112-
else
113-
reason = errno;
114-
#else
115-
reason = errno;
116-
if (reason == EINTR || reason == EAGAIN)
117-
continue;
118-
#endif
119-
120-
if (log)
121-
*log << "Error " << reason << " reading from input file.\n";
122-
return false;
123-
}
34+
auto status = descriptor->Read(data.data(), length);
35+
if (status.Fail())
36+
return false;
12437

125-
assert(bytes_read >= 0 && (size_t)bytes_read <= length);
126-
ptr += bytes_read;
127-
length -= bytes_read;
128-
}
12938
text += data;
13039
return true;
13140
}

lldb/tools/lldb-dap/IOStream.h

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,45 +9,17 @@
99
#ifndef LLDB_TOOLS_LLDB_DAP_IOSTREAM_H
1010
#define LLDB_TOOLS_LLDB_DAP_IOSTREAM_H
1111

12-
#if defined(_WIN32)
13-
#include "lldb/Host/windows/windows.h"
14-
#include <winsock2.h>
15-
#else
16-
typedef int SOCKET;
17-
#endif
18-
12+
#include "lldb/lldb-forward.h"
1913
#include "llvm/ADT/StringRef.h"
20-
2114
#include <fstream>
2215
#include <string>
2316

24-
// Windows requires different system calls for dealing with sockets and other
25-
// types of files, so we can't simply have one code path that just uses read
26-
// and write everywhere. So we need an abstraction in order to allow us to
27-
// treat them identically.
2817
namespace lldb_dap {
29-
struct StreamDescriptor {
30-
StreamDescriptor();
31-
~StreamDescriptor();
32-
StreamDescriptor(StreamDescriptor &&other);
33-
34-
StreamDescriptor &operator=(StreamDescriptor &&other);
35-
36-
static StreamDescriptor from_socket(SOCKET s, bool close);
37-
static StreamDescriptor from_file(int fd, bool close);
38-
39-
bool m_is_socket = false;
40-
bool m_close = false;
41-
union {
42-
int m_fd;
43-
SOCKET m_socket;
44-
};
45-
};
4618

4719
struct InputStream {
48-
StreamDescriptor descriptor;
20+
lldb::IOObjectSP descriptor;
4921

50-
explicit InputStream(StreamDescriptor descriptor)
22+
explicit InputStream(lldb::IOObjectSP descriptor)
5123
: descriptor(std::move(descriptor)) {}
5224

5325
bool read_full(std::ofstream *log, size_t length, std::string &text);
@@ -58,9 +30,9 @@ struct InputStream {
5830
};
5931

6032
struct OutputStream {
61-
StreamDescriptor descriptor;
33+
lldb::IOObjectSP descriptor;
6234

63-
explicit OutputStream(StreamDescriptor descriptor)
35+
explicit OutputStream(lldb::IOObjectSP descriptor)
6436
: descriptor(std::move(descriptor)) {}
6537

6638
bool write_full(llvm::StringRef str);

lldb/tools/lldb-dap/lldb-dap.cpp

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "RunInTerminal.h"
1616
#include "lldb/API/SBStream.h"
1717
#include "lldb/Host/Config.h"
18+
#include "lldb/Host/File.h"
1819
#include "lldb/Host/MainLoop.h"
1920
#include "lldb/Host/MainLoopBase.h"
2021
#include "lldb/Host/Socket.h"
@@ -80,7 +81,11 @@ typedef int socklen_t;
8081
#endif
8182

8283
using namespace lldb_dap;
83-
using lldb_private::NativeSocket;
84+
using lldb_private::File;
85+
using lldb_private::IOObject;
86+
using lldb_private::MainLoop;
87+
using lldb_private::MainLoopBase;
88+
using lldb_private::NativeFile;
8489
using lldb_private::Socket;
8590
using lldb_private::Status;
8691

@@ -308,14 +313,14 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
308313
// address.
309314
llvm::outs().flush();
310315

311-
static lldb_private::MainLoop g_loop;
316+
static MainLoop g_loop;
312317
llvm::sys::SetInterruptFunction([]() {
313318
g_loop.AddPendingCallback(
314-
[](lldb_private::MainLoopBase &loop) { loop.RequestTermination(); });
319+
[](MainLoopBase &loop) { loop.RequestTermination(); });
315320
});
316321
std::condition_variable dap_sessions_condition;
317322
std::mutex dap_sessions_mutex;
318-
std::map<Socket *, DAP *> dap_sessions;
323+
std::map<IOObject *, DAP *> dap_sessions;
319324
unsigned int clientCount = 0;
320325
auto handle = listener->Accept(g_loop, [=, &dap_sessions_condition,
321326
&dap_sessions_mutex, &dap_sessions,
@@ -329,18 +334,15 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
329334
<< " client connected: " << name << "\n";
330335
}
331336

337+
lldb::IOObjectSP io(std::move(sock));
338+
332339
// Move the client into a background thread to unblock accepting the next
333340
// client.
334341
std::thread client([=, &dap_sessions_condition, &dap_sessions_mutex,
335-
&dap_sessions, sock = std::move(sock)]() {
342+
&dap_sessions]() {
336343
llvm::set_thread_name(name + ".runloop");
337-
StreamDescriptor input =
338-
StreamDescriptor::from_socket(sock->GetNativeSocket(), false);
339-
// Close the output last for the best chance at error reporting.
340-
StreamDescriptor output =
341-
StreamDescriptor::from_socket(sock->GetNativeSocket(), false);
342-
DAP dap = DAP(name, program_path, log, std::move(input),
343-
std::move(output), default_repl_mode, pre_init_commands);
344+
DAP dap = DAP(name, program_path, log, io, io, default_repl_mode,
345+
pre_init_commands);
344346

345347
if (auto Err = dap.ConfigureIO()) {
346348
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
@@ -352,7 +354,7 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
352354

353355
{
354356
std::scoped_lock<std::mutex> lock(dap_sessions_mutex);
355-
dap_sessions[sock.get()] = &dap;
357+
dap_sessions[io.get()] = &dap;
356358
}
357359

358360
if (auto Err = dap.Loop()) {
@@ -368,7 +370,7 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
368370
}
369371

370372
std::unique_lock<std::mutex> lock(dap_sessions_mutex);
371-
dap_sessions.erase(sock.get());
373+
dap_sessions.erase(io.get());
372374
std::notify_all_at_thread_exit(dap_sessions_condition, std::move(lock));
373375
});
374376
client.detach();
@@ -560,8 +562,10 @@ int main(int argc, char *argv[]) {
560562
return EXIT_FAILURE;
561563
}
562564

563-
StreamDescriptor input = StreamDescriptor::from_file(fileno(stdin), false);
564-
StreamDescriptor output = StreamDescriptor::from_file(stdout_fd, false);
565+
lldb::IOObjectSP input = std::make_shared<NativeFile>(
566+
fileno(stdin), File::eOpenOptionReadOnly, true);
567+
lldb::IOObjectSP output = std::make_shared<NativeFile>(
568+
stdout_fd, File::eOpenOptionWriteOnly, false);
565569

566570
DAP dap = DAP("stdin/stdout", program_path, log.get(), std::move(input),
567571
std::move(output), default_repl_mode, pre_init_commands);

0 commit comments

Comments
 (0)