[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
John Harrison via lldb-commits
lldb-commits at lists.llvm.org
Fri Nov 22 17:13:13 PST 2024
================
@@ -137,42 +141,232 @@ lldb::SBValueList *GetTopLevelScope(DAP &dap, int64_t variablesReference) {
}
}
-SOCKET AcceptConnection(DAP &dap, int portno) {
- // Accept a socket connection from any host on "portno".
- SOCKET newsockfd = -1;
- struct sockaddr_in serv_addr, cli_addr;
+/// Redirect stdout and stderr fo the IDE's console output.
+///
+/// Errors in this operation will be printed to the log file and the IDE's
+/// console output as well.
+///
+/// \return
+/// A fd pointing to the original stdout.
+void SetupRedirection(DAP &dap, int stdoutfd = -1, int stderrfd = -1) {
+ auto output_callback_stderr = [&dap](llvm::StringRef data) {
+ dap.SendOutput(OutputType::Stderr, data);
+ };
+ auto output_callback_stdout = [&dap](llvm::StringRef data) {
+ dap.SendOutput(OutputType::Stdout, data);
+ };
+
+ llvm::Expected<int> new_stdout_fd =
+ RedirectFd(stdoutfd, output_callback_stdout);
+ if (auto err = new_stdout_fd.takeError()) {
+ std::string error_message = llvm::toString(std::move(err));
+ if (dap.log)
+ *dap.log << error_message << std::endl;
+ output_callback_stderr(error_message);
+ }
+ dap.out = lldb::SBFile(new_stdout_fd.get(), "w", false);
+
+ llvm::Expected<int> new_stderr_fd =
+ RedirectFd(stderrfd, output_callback_stderr);
+ if (auto err = new_stderr_fd.takeError()) {
+ std::string error_message = llvm::toString(std::move(err));
+ if (dap.log)
+ *dap.log << error_message << std::endl;
+ output_callback_stderr(error_message);
+ }
+ dap.err = lldb::SBFile(new_stderr_fd.get(), "w", false);
+}
+
+void HandleClient(int clientfd, llvm::StringRef program_path,
+ const std::vector<std::string> &pre_init_commands,
+ std::shared_ptr<std::ofstream> log,
+ ReplMode default_repl_mode) {
+ if (log)
+ *log << "client[" << clientfd << "] connected\n";
+ DAP dap = DAP(program_path, log, default_repl_mode, pre_init_commands);
+ dap.debug_adaptor_path = program_path;
+
+ SetupRedirection(dap);
+ RegisterRequestCallbacks(dap);
+
+ dap.input.descriptor = StreamDescriptor::from_socket(clientfd, false);
+ dap.output.descriptor = StreamDescriptor::from_socket(clientfd, false);
+
+ for (const std::string &arg : pre_init_commands) {
+ dap.pre_init_commands.push_back(arg);
+ }
+
+ if (auto Err = dap.Loop()) {
+ if (log)
+ *log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n";
+ }
+
+ if (log)
+ *log << "client[" << clientfd << "] connection closed\n";
+#if defined(_WIN32)
+ closesocket(clientfd);
+#else
+ close(clientfd);
+#endif
+}
+
+std::error_code getLastSocketErrorCode() {
+#ifdef _WIN32
+ return std::error_code(::WSAGetLastError(), std::system_category());
+#else
+ return llvm::errnoAsErrorCode();
+#endif
+}
+
+llvm::Expected<int> getSocketFD(llvm::StringRef path) {
+ if (llvm::sys::fs::exists(path) && (::remove(path.str().c_str()) == -1)) {
+ return llvm::make_error<llvm::StringError>(getLastSocketErrorCode(),
+ "Remove existing socket failed");
+ }
+
+ SOCKET sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sockfd == -1) {
+ return llvm::make_error<llvm::StringError>(getLastSocketErrorCode(),
+ "Create socket failed");
+ }
+
+ struct sockaddr_un addr;
+ bzero(&addr, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, path.str().c_str(), sizeof(addr.sun_path) - 1);
+
+ if (::bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+#if defined(_WIN32)
+ closesocket(sockfd);
+#else
+ close(sockfd);
+#endif
+ return llvm::make_error<llvm::StringError>(getLastSocketErrorCode(),
+ "Socket bind() failed");
+ }
+
+ if (listen(sockfd, llvm::hardware_concurrency().compute_thread_count()) < 0) {
+#if defined(_WIN32)
+ closesocket(sockfd);
+#else
+ close(sockfd);
+#endif
+ return llvm::make_error<llvm::StringError>(getLastSocketErrorCode(),
+ "Socket listen() failed");
+ }
+
+ return sockfd;
+}
+
+llvm::Expected<int> getSocketFD(int portno) {
SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
- if (dap.log)
- *dap.log << "error: opening socket (" << strerror(errno) << ")"
- << std::endl;
- } else {
- memset((char *)&serv_addr, 0, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- // serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- serv_addr.sin_port = htons(portno);
- if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
- if (dap.log)
- *dap.log << "error: binding socket (" << strerror(errno) << ")"
- << std::endl;
- } else {
- listen(sockfd, 5);
- socklen_t clilen = sizeof(cli_addr);
- newsockfd =
- llvm::sys::RetryAfterSignal(static_cast<SOCKET>(-1), accept, sockfd,
- (struct sockaddr *)&cli_addr, &clilen);
- if (newsockfd < 0)
- if (dap.log)
- *dap.log << "error: accept (" << strerror(errno) << ")" << std::endl;
- }
+ return llvm::make_error<llvm::StringError>(getLastSocketErrorCode(),
+ "Create socket failed");
+ }
+
+ struct sockaddr_in serv_addr;
+ bzero(&serv_addr, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ // serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
----------------
ashgti wrote:
This was here before my change, but I refactored this and made some new helpers to support different kinds of sockets.
https://github.com/llvm/llvm-project/pull/116392
More information about the lldb-commits
mailing list