Skip to content

Commit 9af1b00

Browse files
committed
[lldb-dap] Add optional TTL argument when using --connection
1 parent 62ff9ac commit 9af1b00

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

lldb/tools/lldb-dap/Options.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,10 @@ def pre_init_command: S<"pre-init-command">,
6161
def: Separate<["-"], "c">,
6262
Alias<pre_init_command>,
6363
HelpText<"Alias for --pre-init-command">;
64+
65+
def time_to_live: S<"time-to-live">,
66+
MetaVarName<"<ttl>">,
67+
HelpText<"When using --connection, the number of milliseconds to wait "
68+
"for new connections at the beginning and after all clients have "
69+
"disconnected. Not specifying this argument or specifying "
70+
"non-positive values will wait indefinitely.">;

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

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ validateConnection(llvm::StringRef conn) {
258258
static llvm::Error
259259
serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
260260
Log *log, const ReplMode default_repl_mode,
261-
const std::vector<std::string> &pre_init_commands) {
261+
const std::vector<std::string> &pre_init_commands, int ttl) {
262262
Status status;
263263
static std::unique_ptr<Socket> listener = Socket::Create(protocol, status);
264264
if (status.Fail()) {
@@ -283,6 +283,21 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
283283
g_loop.AddPendingCallback(
284284
[](MainLoopBase &loop) { loop.RequestTermination(); });
285285
});
286+
static MainLoopBase::TimePoint ttl_time_point;
287+
static std::mutex ttl_mutex;
288+
if (ttl > 0) {
289+
std::scoped_lock<std::mutex> lock(ttl_mutex);
290+
MainLoopBase::TimePoint future =
291+
std::chrono::steady_clock::now() + std::chrono::milliseconds(ttl);
292+
ttl_time_point = future;
293+
g_loop.AddCallback(
294+
[future](MainLoopBase &loop) {
295+
if (ttl_time_point == future) {
296+
loop.RequestTermination();
297+
}
298+
},
299+
future);
300+
}
286301
std::condition_variable dap_sessions_condition;
287302
std::mutex dap_sessions_mutex;
288303
std::map<MainLoop *, DAP *> dap_sessions;
@@ -291,6 +306,12 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
291306
&dap_sessions_mutex, &dap_sessions,
292307
&clientCount](
293308
std::unique_ptr<Socket> sock) {
309+
if (ttl > 0) {
310+
// Reset the keep alive timer, because we won't be killing the server
311+
// while this connection is being served.
312+
std::scoped_lock<std::mutex> lock(ttl_mutex);
313+
ttl_time_point = MainLoopBase::TimePoint();
314+
}
294315
std::string client_name = llvm::formatv("client_{0}", clientCount++).str();
295316
DAP_LOG(log, "({0}) client connected", client_name);
296317

@@ -327,6 +348,23 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
327348
std::unique_lock<std::mutex> lock(dap_sessions_mutex);
328349
dap_sessions.erase(&loop);
329350
std::notify_all_at_thread_exit(dap_sessions_condition, std::move(lock));
351+
352+
if (ttl > 0) {
353+
// Start the countdown to kill the server at the end of each connection.
354+
std::scoped_lock<std::mutex> lock(ttl_mutex);
355+
MainLoopBase::TimePoint future =
356+
std::chrono::steady_clock::now() + std::chrono::milliseconds(ttl);
357+
// We don't need to take the max of `keep_alive_up_to` and `future`,
358+
// because `future` must be the latest.
359+
ttl_time_point = future;
360+
g_loop.AddCallback(
361+
[future](MainLoopBase &loop) {
362+
if (ttl_time_point == future) {
363+
loop.RequestTermination();
364+
}
365+
},
366+
future);
367+
}
330368
});
331369
client.detach();
332370
});
@@ -509,6 +547,17 @@ int main(int argc, char *argv[]) {
509547
}
510548

511549
if (!connection.empty()) {
550+
int ttl = 0;
551+
llvm::opt::Arg *time_to_live = input_args.getLastArg(OPT_time_to_live);
552+
if (time_to_live) {
553+
llvm::StringRef time_to_live_value = time_to_live->getValue();
554+
if (time_to_live_value.getAsInteger(10, ttl)) {
555+
llvm::errs() << "'" << time_to_live_value
556+
<< "' is not a valid time-to-live value\n";
557+
return EXIT_FAILURE;
558+
}
559+
}
560+
512561
auto maybeProtoclAndName = validateConnection(connection);
513562
if (auto Err = maybeProtoclAndName.takeError()) {
514563
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
@@ -520,7 +569,7 @@ int main(int argc, char *argv[]) {
520569
std::string name;
521570
std::tie(protocol, name) = *maybeProtoclAndName;
522571
if (auto Err = serveConnection(protocol, name, log.get(), default_repl_mode,
523-
pre_init_commands)) {
572+
pre_init_commands, ttl)) {
524573
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
525574
"Connection failed: ");
526575
return EXIT_FAILURE;

0 commit comments

Comments
 (0)