@@ -223,6 +223,36 @@ static int DuplicateFileDescriptor(int fd) {
223223#endif
224224}
225225
226+ static void ResetTimeToLive (std::mutex &ttl_mutex,
227+ MainLoopBase::TimePoint &ttl_time_point) {
228+ std::scoped_lock<std::mutex> lock (ttl_mutex);
229+ ttl_time_point = MainLoopBase::TimePoint ();
230+ }
231+
232+ static void TrackTimeToLive (MainLoop &loop, std::mutex &ttl_mutex,
233+ MainLoopBase::TimePoint &ttl_time_point,
234+ std::chrono::seconds ttl_seconds) {
235+ MainLoopBase::TimePoint next_checkpoint =
236+ std::chrono::steady_clock::now () + std::chrono::seconds (ttl_seconds);
237+ {
238+ std::scoped_lock<std::mutex> lock (ttl_mutex);
239+ // We don't need to take the max of `ttl_time_point` and `next_checkpoint`,
240+ // because `next_checkpoint` must be the latest.
241+ ttl_time_point = next_checkpoint;
242+ }
243+ loop.AddCallback (
244+ [&ttl_mutex, &ttl_time_point, next_checkpoint](MainLoopBase &loop) {
245+ bool should_request_terimation;
246+ {
247+ std::scoped_lock<std::mutex> lock (ttl_mutex);
248+ should_request_terimation = ttl_time_point == next_checkpoint;
249+ }
250+ if (should_request_terimation)
251+ loop.RequestTermination ();
252+ },
253+ next_checkpoint);
254+ }
255+
226256static llvm::Expected<std::pair<Socket::SocketProtocol, std::string>>
227257validateConnection (llvm::StringRef conn) {
228258 auto uri = lldb_private::URI::Parse (conn);
@@ -258,7 +288,8 @@ validateConnection(llvm::StringRef conn) {
258288static llvm::Error
259289serveConnection (const Socket::SocketProtocol &protocol, const std::string &name,
260290 Log *log, const ReplMode default_repl_mode,
261- const std::vector<std::string> &pre_init_commands, int ttl) {
291+ const std::vector<std::string> &pre_init_commands,
292+ std::optional<std::chrono::seconds> ttl_seconds) {
262293 Status status;
263294 static std::unique_ptr<Socket> listener = Socket::Create (protocol, status);
264295 if (status.Fail ()) {
@@ -283,21 +314,10 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
283314 g_loop.AddPendingCallback (
284315 [](MainLoopBase &loop) { loop.RequestTermination (); });
285316 });
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- }
317+ static MainLoopBase::TimePoint g_ttl_time_point;
318+ static std::mutex g_ttl_mutex;
319+ if (ttl_seconds)
320+ TrackTimeToLive (g_loop, g_ttl_mutex, g_ttl_time_point, ttl_seconds.value ());
301321 std::condition_variable dap_sessions_condition;
302322 std::mutex dap_sessions_mutex;
303323 std::map<MainLoop *, DAP *> dap_sessions;
@@ -306,12 +326,10 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
306326 &dap_sessions_mutex, &dap_sessions,
307327 &clientCount](
308328 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- }
329+ // Reset the keep alive timer, because we won't be killing the server
330+ // while this connection is being served.
331+ if (ttl_seconds)
332+ ResetTimeToLive (g_ttl_mutex, g_ttl_time_point);
315333 std::string client_name = llvm::formatv (" client_{0}" , clientCount++).str ();
316334 DAP_LOG (log, " ({0}) client connected" , client_name);
317335
@@ -349,22 +367,10 @@ serveConnection(const Socket::SocketProtocol &protocol, const std::string &name,
349367 dap_sessions.erase (&loop);
350368 std::notify_all_at_thread_exit (dap_sessions_condition, std::move (lock));
351369
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- }
370+ // Start the countdown to kill the server at the end of each connection.
371+ if (ttl_seconds)
372+ TrackTimeToLive (g_loop, g_ttl_mutex, g_ttl_time_point,
373+ ttl_seconds.value ());
368374 });
369375 client.detach ();
370376 });
@@ -547,15 +553,19 @@ int main(int argc, char *argv[]) {
547553 }
548554
549555 if (!connection.empty ()) {
550- int ttl = 0 ;
556+ std::optional<std::chrono::seconds> ttl_seconds ;
551557 llvm::opt::Arg *time_to_live = input_args.getLastArg (OPT_time_to_live);
552558 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 " ;
559+ llvm::StringRef time_to_live_string_value = time_to_live->getValue ();
560+ int time_to_live_int_value;
561+ if (time_to_live_string_value.getAsInteger (10 , time_to_live_int_value)) {
562+ llvm::errs () << " '" << time_to_live_string_value
563+ << " ' is not a valid time-to-live value\n " ;
557564 return EXIT_FAILURE;
558565 }
566+ // Ignore non-positive values.
567+ if (time_to_live_int_value > 0 )
568+ ttl_seconds = std::chrono::seconds (time_to_live_int_value);
559569 }
560570
561571 auto maybeProtoclAndName = validateConnection (connection);
@@ -569,7 +579,7 @@ int main(int argc, char *argv[]) {
569579 std::string name;
570580 std::tie (protocol, name) = *maybeProtoclAndName;
571581 if (auto Err = serveConnection (protocol, name, log.get (), default_repl_mode,
572- pre_init_commands, ttl )) {
582+ pre_init_commands, ttl_seconds )) {
573583 llvm::logAllUnhandledErrors (std::move (Err), llvm::errs (),
574584 " Connection failed: " );
575585 return EXIT_FAILURE;
0 commit comments