================ @@ -5058,72 +5053,148 @@ int main(int argc, char *argv[]) { auto terminate_debugger = llvm::make_scope_exit([] { lldb::SBDebugger::Terminate(); }); - StreamDescriptor input; - StreamDescriptor output; - std::FILE *redirectOut = nullptr; - std::FILE *redirectErr = nullptr; - if (portno != -1) { - printf("Listening on port %i...\n", portno); - SOCKET socket_fd = AcceptConnection(log.get(), portno); - if (socket_fd < 0) - return EXIT_FAILURE; + std::vector<std::string> pre_init_commands; + for (const std::string &arg : + input_args.getAllArgValues(OPT_pre_init_command)) { + pre_init_commands.push_back(arg); + } - input = StreamDescriptor::from_socket(socket_fd, true); - output = StreamDescriptor::from_socket(socket_fd, false); - } else { -#if defined(_WIN32) - // Windows opens stdout and stdin in text mode which converts \n to 13,10 - // while the value is just 10 on Darwin/Linux. Setting the file mode to - // binary fixes this. - int result = _setmode(fileno(stdout), _O_BINARY); - assert(result); - result = _setmode(fileno(stdin), _O_BINARY); - UNUSED_IF_ASSERT_DISABLED(result); - assert(result); -#endif + auto HandleClient = + [=, log = log.get()](std::string name, StreamDescriptor input, + StreamDescriptor output, std::FILE *redirectOut, + std::FILE *redirectErr) -> bool { + DAP dap = DAP(name, program_path.str(), log, default_repl_mode, + std::move(input), std::move(output)); - int stdout_fd = DuplicateFileDescriptor(fileno(stdout)); - if (stdout_fd == -1) { + // stdout/stderr redirection to the IDE's console + if (auto Err = dap.ConfigureIO(redirectOut, redirectErr)) { llvm::logAllUnhandledErrors( - llvm::errorCodeToError(llvm::errnoAsErrorCode()), llvm::errs(), - "Failed to configure stdout redirect: "); + std::move(Err), llvm::errs(), + "Failed to configure lldb-dap IO operations: "); return EXIT_FAILURE; } - redirectOut = stdout; - redirectErr = stderr; + RegisterRequestCallbacks(dap); - input = StreamDescriptor::from_file(fileno(stdin), false); - output = StreamDescriptor::from_file(stdout_fd, false); - } + dap.pre_init_commands = pre_init_commands; - DAP dap = DAP(program_path.str(), log.get(), default_repl_mode, - std::move(input), std::move(output)); + // used only by TestVSCode_redirection_to_console.py + if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) + redirection_test(); - // stdout/stderr redirection to the IDE's console - if (auto Err = dap.ConfigureIO(redirectOut, redirectErr)) { - llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), - "Failed to configure lldb-dap IO operations: "); - return EXIT_FAILURE; - } + if (auto Err = dap.Loop()) { + if (log) + *log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; + return false; + } + return true; + }; - RegisterRequestCallbacks(dap); + if (!connection.empty()) { + auto maybeProtoclAndName = parseConnection(connection); + if (auto Err = maybeProtoclAndName.takeError()) { + llvm::errs() << "Invalid connection specification " << Err << "\n"; + return EXIT_FAILURE; + } - for (const std::string &arg : - input_args.getAllArgValues(OPT_pre_init_command)) { - dap.pre_init_commands.push_back(arg); - } + Socket::SocketProtocol protocol; + std::string name; + std::tie(protocol, name) = *maybeProtoclAndName; - // used only by TestVSCode_redirection_to_console.py - if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) - redirection_test(); + Status error; + std::unique_ptr<Socket> listener = Socket::Create(protocol, error); + if (error.Fail()) { + llvm::errs() << "Failed to create listener for protocol " + << Socket::FindSchemeByProtocol(protocol) + << ", error: " << error.takeError() << "\n"; + return EXIT_FAILURE; + } - bool CleanExit = true; - if (auto Err = dap.Loop()) { + error = listener->Listen(name, /* backlog */ 5); + if (error.Fail()) { + llvm::errs() << "Failed to listen, error: " << error.takeError() << "\n"; + return EXIT_FAILURE; + } + + std::string address = + llvm::join(listener->GetListeningConnectionURI(), ", "); if (log) - *log << "Transport Error: " << llvm::toString(std::move(Err)) << "\n"; - CleanExit = false; + *log << "started with connection listeners " << address << "\n"; + + llvm::outs() << "Listening for: " << address << "\n"; + // Ensure listening address are flushed for calles to retrieve the resolve + // address. + llvm::outs().flush(); + + MainLoop mainloop; + mainloop.RegisterSignal( + SIGHUP, [](auto &RL) { RL.RequestTermination(); }, error); + + unsigned int clientCount = 0; + auto OnAccept = [=, log = log.get(), + &clientCount](std::unique_ptr<Socket> client) { + std::string name = llvm::formatv("client_{0}", clientCount++).str(); + + if (log) { + auto now = std::chrono::duration<double>( + std::chrono::system_clock::now().time_since_epoch()); + *log << llvm::formatv("{0:f9} client connected: {1}", now.count(), name) + .str() + << std::endl; + } + // Start a thread for each connection, unblocking the listening thread. + std::thread([=, client = std::move(client)]() { + HandleClient( + name, + StreamDescriptor::from_socket(client->GetNativeSocket(), false), + StreamDescriptor::from_socket(client->GetNativeSocket(), false), + /*=redirectOut*/ nullptr, /*=redirectErr*/ nullptr); ---------------- labath wrote:
This is the usual syntax for these. ```suggestion /*redirectOut=*/nullptr, /*redirectErr=*/nullptr); ``` https://github.com/llvm/llvm-project/pull/116392 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits