From 7ae7b8481ad417c630a8e3433ee5d81744aeadc9 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Mon, 11 Mar 2024 13:35:36 +0100 Subject: [PATCH] monitor: send a notification when an inferior vanished Fixes #5139 --- repos/os/src/monitor/gdb_stub.h | 45 ++++++++++++++++++++++++- repos/os/src/monitor/main.cc | 3 +- repos/os/src/monitor/monitored_thread.h | 1 + 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/repos/os/src/monitor/gdb_stub.h b/repos/os/src/monitor/gdb_stub.h index 4cdbabb8ee..a16bef89b1 100644 --- a/repos/os/src/monitor/gdb_stub.h +++ b/repos/os/src/monitor/gdb_stub.h @@ -157,10 +157,46 @@ struct Monitor::Gdb::State : Noncopyable Max_response max_response; - void flush(Inferior_pd &pd) + /** + * Try to notify GDB about a vanished inferior + */ + void try_send_exit_notification(Output &out, int pid) + { + if (!notification_in_progress) { + + notification_in_progress = true; + + using Stop_reply_signal = Monitored_thread::Stop_reply_signal; + + if (pid > 0) + gdb_notification(out, [&] (Output &out) { + print(out, "Stop:X", + Gdb_hex((uint8_t)Stop_reply_signal::KILL), + ";process:", Gdb_hex(pid)); + }); + else + gdb_notification(out, [&] (Output &out) { + print(out, "Stop:X", + Gdb_hex((uint8_t)Stop_reply_signal::KILL)); + }); + + } else { + /* + * Only one notification can be in flight and we don't want to + * keep exit information in the monitor for later because GDB + * might never consume it. There will be another notification + * attempt when GDB calls 'vCont' for the vanished inferior + * (again) in the future. + */ + } + } + + void flush(Inferior_pd &pd, Output &out) { if (_current.constructed() && _current->pd.id() == pd.id()) _current.destruct(); + + try_send_exit_notification(out, (int)pd.id()); } void flush(Monitored_thread &thread) @@ -883,6 +919,8 @@ struct vCont : Command_without_separator int pid = -1; int tid = -1; + bool inferior_found = false; + with_skipped_prefix(arg, ":", [&] (Const_byte_range_ptr const &arg) { thread_id(arg, pid, tid); }); @@ -894,6 +932,8 @@ struct vCont : Command_without_separator if ((pid != -1) && ((int)inferior.id() != pid)) return; + inferior_found = true; + inferior.for_each_thread([&] (Monitored_thread &thread) { if (tid == 0) @@ -905,6 +945,9 @@ struct vCont : Command_without_separator fn(inferior, thread); }); }); + + if (!inferior_found) + state.try_send_exit_notification(out, pid); }; using Stop_state = Monitored_thread::Stop_state; diff --git a/repos/os/src/monitor/main.cc b/repos/os/src/monitor/main.cc index 52784dd5e8..d21241d82c 100644 --- a/repos/os/src/monitor/main.cc +++ b/repos/os/src/monitor/main.cc @@ -162,7 +162,8 @@ struct Monitor::Main : Sandbox::State_handler, void flush(Inferior_pd &pd) { - _state.flush(pd); + Terminal_output output { ._write_fn { _terminal } }; + _state.flush(pd, output.buffered); _memory_accessor.flush(); } diff --git a/repos/os/src/monitor/monitored_thread.h b/repos/os/src/monitor/monitored_thread.h index 27db83dbe1..606f9734af 100644 --- a/repos/os/src/monitor/monitored_thread.h +++ b/repos/os/src/monitor/monitored_thread.h @@ -73,6 +73,7 @@ struct Monitor::Monitored_thread : Monitored_rpc_object ILL = 4, TRAP = 5, FPE = 8, + KILL = 9, SEGV = 11 };