@@ -258,7 +258,7 @@ validateConnection(llvm::StringRef conn) {
258258static llvm::Error
259259serveConnection (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