================ @@ -5058,72 +5053,144 @@ 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 RunDAP = [](llvm::StringRef program_path, ReplMode repl_mode, + std::vector<std::string> pre_init_commands, + std::ofstream *log, std::string name, StreamDescriptor input, + StreamDescriptor output, std::FILE *redirectOut = nullptr, + std::FILE *redirectErr = nullptr) -> bool { + DAP dap = DAP(name, program_path, log, std::move(input), std::move(output), + repl_mode, pre_init_commands); - 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 false; + } + + RegisterRequestCallbacks(dap); + + // used only by TestVSCode_redirection_to_console.py + if (getenv("LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION") != nullptr) + redirection_test(); + + if (auto Err = dap.Loop()) { + std::string errorMessage = llvm::toString(std::move(Err)); + if (log) + *log << "Transport Error: " << errorMessage << "\n"; + return false; + } + return true; + }; + + if (!connection.empty()) { + auto maybeProtoclAndName = validateConnection(connection); + if (auto Err = maybeProtoclAndName.takeError()) { + llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), + "Invalid connection: "); return EXIT_FAILURE; } - redirectOut = stdout; - redirectErr = stderr; + Socket::SocketProtocol protocol; + std::string name; + std::tie(protocol, name) = *maybeProtoclAndName; - input = StreamDescriptor::from_file(fileno(stdin), false); - output = StreamDescriptor::from_file(stdout_fd, false); - } + Status error; + std::unique_ptr<Socket> listener = Socket::Create(protocol, error); + if (error.Fail()) { + llvm::logAllUnhandledErrors(error.takeError(), llvm::errs(), + "Failed to create socket listener: "); + return EXIT_FAILURE; + } - DAP dap = DAP(program_path.str(), log.get(), default_repl_mode, - std::move(input), std::move(output)); + error = listener->Listen(name, /* backlog */ 5); + if (error.Fail()) { + llvm::logAllUnhandledErrors(error.takeError(), llvm::errs(), + "Failed to listen for connections: "); + return EXIT_FAILURE; + } - // 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; - } + std::string address = + llvm::join(listener->GetListeningConnectionURI(), ", "); + if (log) + *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(); + + llvm::DefaultThreadPool pool(llvm::optimal_concurrency()); ---------------- labath wrote:
Are you sure about that? I haven't tried this, but looking at the source code, it definitely looks like it is [limiting something](https://github.com/llvm/llvm-project/blob/409fa785d99b3e9f8210b72641d58947e6687fb1/llvm/lib/Support/Threading.cpp#L60). And although the implementation appears to be stubbed out, it looks like it has some ambition to mess with [cpu affinities](https://github.com/llvm/llvm-project/blob/409fa785d99b3e9f8210b72641d58947e6687fb1/llvm/include/llvm/Support/Threading.h#L135) which, I guess, is fine if you have a a lot of work to do and you want to avoid cpu migrations, but maybe not so fine when in practice you just have one task most of the time, and you want to make sure that task gets access to all cpus. I have feeling this class just wasn't designed for this use case. We may need to roll our own solution. The detached thread approach is "almost" right in that we don't care about a single thread exiting. What we want to wait for is *all* threads to exit. So maybe have a counter of active threads which is decreased (and signaled with [std::notify_all_at_thread_exit](https://en.cppreference.com/w/cpp/thread/notify_all_at_thread_exit)?) when the thread exits? 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