From d0d7b73e9efc11b238d77785450a2369cf78b276 Mon Sep 17 00:00:00 2001 From: Samuel Powell Date: Thu, 29 Aug 2024 16:12:51 -0400 Subject: [PATCH 1/6] Initial steps, min. working to attach debugger externally --- src/TiledArray/util/bug.cpp | 48 +++++++++++++++++++++++++++++++++++++ src/TiledArray/util/bug.h | 3 +++ 2 files changed, 51 insertions(+) diff --git a/src/TiledArray/util/bug.cpp b/src/TiledArray/util/bug.cpp index ff37f14343..74024fff7b 100644 --- a/src/TiledArray/util/bug.cpp +++ b/src/TiledArray/util/bug.cpp @@ -180,6 +180,11 @@ void Debugger::default_cmd() { } } +const std::string Debugger::gdb_cmd_ = + "gdb -ex \"set variable debugger_ready_=1\" --pid=$(PID) $(EXEC)"; +const std::string Debugger::lldb_cmd_ = + "lldb -p $(PID) -o \"expr debugger_ready_=1\""; + void Debugger::resolve_cmd_alias() { if (cmd_ == "gdb_xterm") { cmd_ = @@ -192,6 +197,28 @@ void Debugger::resolve_cmd_alias() { } } +std::string Debugger::replace_macros(std::string str) { + if (!str.empty()) { + int pid = getpid(); + std::string::size_type pos; + std::string pidvar("$(PID)"); + while ((pos = str.find(pidvar)) != std::string::npos) { + std::string pidstr; + pidstr += std::to_string(pid); + str.replace(pos, pidvar.size(), pidstr); + } + std::string execvar("$(EXEC)"); + while ((pos = str.find(execvar)) != std::string::npos) { + str.replace(pos, execvar.size(), exec_); + } + std::string prefixvar("$(PREFIX)"); + while ((pos = str.find(prefixvar)) != std::string::npos) { + str.replace(pos, prefixvar.size(), prefix_); + } + } + return str; +} + void Debugger::set_cmd(const char *cmd) { if (cmd) { cmd_ = cmd; @@ -262,6 +289,27 @@ void Debugger::debug(const char *reason) { ; } } + } // Here, need handling of cmd_ empty + if (sleep_) { + std::cout << prefix_ << "Debugger: sleeping " << sleep_ + << " seconds to wait for debugger ..." << std::endl; + sleep(sleep_); + } + if (wait_for_debugger_) { + std::cout << prefix_ << "Debugger: waiting for the user ..."; + if (cmd_.empty()) { + std::cout << " attach debugger to process " + << std::to_string(getpid()) + << " as follows:" << std::endl + << prefix_ << "Debugger: - if using gdb: " + << replace_macros(gdb_cmd_) << std::endl + << prefix_ << "Debugger: - if using lldb: " + << replace_macros(lldb_cmd_); + } + + std::cout << prefix_ << ": waiting for the user ..." << std::endl; + while (!debugger_ready_) + ; } } diff --git a/src/TiledArray/util/bug.h b/src/TiledArray/util/bug.h index 2d217ceaee..0aadd3927e 100644 --- a/src/TiledArray/util/bug.h +++ b/src/TiledArray/util/bug.h @@ -384,6 +384,9 @@ class Debugger { private: /// Replaces alias in cmd_ with its full form void resolve_cmd_alias(); + std::string replace_macros(std::string cmd); + static const std::string gdb_cmd_; + static const std::string lldb_cmd_; }; /// Use this to create a Debugger object and make it the default From 23dc95404cea77df70f7a89391bab0949a040709 Mon Sep 17 00:00:00 2001 From: Samuel Powell Date: Mon, 16 Sep 2024 11:25:10 -0400 Subject: [PATCH 2/6] Allow attaching debugger via cl, enable prelaunch actions, cleanup --- src/TiledArray/util/bug.cpp | 129 ++++++++++++++---------------------- src/TiledArray/util/bug.h | 20 ++++-- 2 files changed, 66 insertions(+), 83 deletions(-) diff --git a/src/TiledArray/util/bug.cpp b/src/TiledArray/util/bug.cpp index 74024fff7b..57e96c162d 100644 --- a/src/TiledArray/util/bug.cpp +++ b/src/TiledArray/util/bug.cpp @@ -77,7 +77,6 @@ Debugger::~Debugger() { for (int i = 0; i < NSIG; i++) { if (mysigs_[i]) signals[i] = nullptr; } - delete[] mysigs_; } void Debugger::init() { @@ -91,7 +90,7 @@ void Debugger::init() { debug_ = 1; wait_for_debugger_ = 1; - mysigs_ = new int[NSIG]; + mysigs_ = std::make_unique(NSIG); for (int i = 0; i < NSIG; i++) { mysigs_[i] = 0; } @@ -187,13 +186,9 @@ const std::string Debugger::lldb_cmd_ = void Debugger::resolve_cmd_alias() { if (cmd_ == "gdb_xterm") { - cmd_ = - "xterm -title \"$(PREFIX)$(EXEC)\" -e gdb -ex \"set variable " - "debugger_ready_=1\" --pid=$(PID) $(EXEC) &"; + cmd_ = "xterm -title \"$(PREFIX)$(EXEC)\" -e " + gdb_cmd_ + " &"; } else if (cmd_ == "lldb_xterm") { - cmd_ = - "xterm -title \"$(PREFIX)$(EXEC)\" -e lldb -p $(PID) -o \"expr " - "debugger_ready_=1\" &"; + cmd_ = "xterm -title \"$(PREFIX)$(EXEC)\" -e " + lldb_cmd_ + " &"; } } @@ -222,10 +217,10 @@ std::string Debugger::replace_macros(std::string str) { void Debugger::set_cmd(const char *cmd) { if (cmd) { cmd_ = cmd; - resolve_cmd_alias(); } else { cmd_.resize(0); } + this->resolve_cmd_alias(); } void Debugger::debug(const char *reason) { @@ -236,80 +231,50 @@ void Debugger::debug(const char *reason) { std::cout << "no reason given"; std::cout << std::endl; - if (!cmd_.empty()) { - int pid = getpid(); - // contruct the command name - std::string cmd = cmd_; - std::string::size_type pos; - std::string pidvar("$(PID)"); - while ((pos = cmd.find(pidvar)) != std::string::npos) { - std::string pidstr; - pidstr += std::to_string(pid); - cmd.replace(pos, pidvar.size(), pidstr); - } - std::string execvar("$(EXEC)"); - while ((pos = cmd.find(execvar)) != std::string::npos) { - cmd.replace(pos, execvar.size(), exec_); - } - std::string prefixvar("$(PREFIX)"); - while ((pos = cmd.find(prefixvar)) != std::string::npos) { - cmd.replace(pos, prefixvar.size(), prefix_); - } - // start the debugger - // before starting the debugger de-register signal handler for SIGTRAP to - // let the debugger take over - release(SIGTRAP); + const std::string cmd = replace_macros(cmd_); + // start the debugger + // before starting the debugger de-register signal handler for SIGTRAP to + // let the debugger take over + release(SIGTRAP); + int system_retvalue = 0; + if (!cmd.empty()) { std::cout << prefix_ << "Debugger: starting \"" << cmd << "\"" << std::endl; - debugger_ready_ = 0; - const auto system_retvalue = system(cmd.c_str()); - if (system_retvalue != 0) { // call to system() failed - std::cout << prefix_ - << "Failed debugger launch: system() did not succeed ..." - << std::endl; - } else { // call to system() succeeded - // wait until the debugger is ready - if (sleep_) { - std::cout << prefix_ << "Sleeping " << sleep_ - << " seconds to wait for debugger ..." << std::endl; - sleep(sleep_); - } - if (wait_for_debugger_) { - std::string make_ready_message; - if (cmd_.find(" gdb ") != std::string::npos || - cmd_.find(" lldb ") != std::string::npos) { - make_ready_message = - " configure debugging session (set breakpoints/watchpoints, " - "etc.) then type 'c' to continue running"; - } - - std::cout << prefix_ << ": waiting for the user ..." - << make_ready_message << std::endl; - while (!debugger_ready_) - ; - } - } - } // Here, need handling of cmd_ empty - if (sleep_) { - std::cout << prefix_ << "Debugger: sleeping " << sleep_ - << " seconds to wait for debugger ..." << std::endl; - sleep(sleep_); + system_retvalue = system(cmd.c_str()); } - if (wait_for_debugger_) { - std::cout << prefix_ << "Debugger: waiting for the user ..."; - if (cmd_.empty()) { - std::cout << " attach debugger to process " - << std::to_string(getpid()) - << " as follows:" << std::endl - << prefix_ << "Debugger: - if using gdb: " - << replace_macros(gdb_cmd_) << std::endl - << prefix_ << "Debugger: - if using lldb: " - << replace_macros(lldb_cmd_); + if (system_retvalue != 0) { + ExEnv::outn() << prefix_ + << "Failed debugger launch: system() did not succeed ..." + << std::endl; + } else { // call to system() succeeded + // wait until the debugger is ready + if (sleep_) { + std::cout << prefix_ << "Debugger: sleeping " << sleep_ + << " seconds to wait for debugger ..." << std::endl; + sleep(sleep_); } + if (wait_for_debugger_) { + std::cout << prefix_ << "Debugger: waiting for the user ..."; + if (cmd_.find(" gdb ") != std::string::npos || + cmd_.find(" lldb ") != std::string::npos) { + std::cout << + " configure debugging session (set breakpoints/watchpoints, " + "etc.) then type 'c' to continue running"; + } else if (cmd.empty()) { + std::cout << " attach debugger to process " + << std::to_string(getpid()) + << " as follows:" << std::endl + << prefix_ << "Debugger: - if using gdb: " + << replace_macros(gdb_cmd_) << std::endl + << prefix_ << "Debugger: - if using lldb: " + << replace_macros(lldb_cmd_); + } + std::cout << std::endl; - std::cout << prefix_ << ": waiting for the user ..." << std::endl; - while (!debugger_ready_) - ; + debugger_ready_ = 0; + while (!debugger_ready_) + ; + } } } @@ -334,6 +299,10 @@ void Debugger::got_signal(int sig) { else signame = "UNKNOWN SIGNAL"; + for (auto const &action: actions_) { + action(); + } + actions_.clear(); if (traceback_) { traceback(signame); } @@ -403,6 +372,10 @@ void Debugger::__traceback(const std::string &prefix, const char *reason) { std::cout << result.str(nframes_to_skip) << std::endl; } +void Debugger::register_prelaunch_action(std::function action) { + actions_.push_back(action); +} + void create_debugger(const char *cmd, const char *exec, std::int64_t rank) { auto debugger = std::make_shared(); if (cmd) debugger->set_cmd(cmd); diff --git a/src/TiledArray/util/bug.h b/src/TiledArray/util/bug.h index 0aadd3927e..f2f284169a 100644 --- a/src/TiledArray/util/bug.h +++ b/src/TiledArray/util/bug.h @@ -291,7 +291,7 @@ class Debugger { bool sleep_; bool wait_for_debugger_; bool handle_sigint_; - int *mysigs_; + std::unique_ptr mysigs_; void init(); @@ -325,11 +325,11 @@ class Debugger { @param reason optional string specifying the reason for traceback */ virtual void traceback(const char *reason); - /// Turn on or off debugging on a signel. The default is on. + /// Turn on or off debugging on a signal. The default is on. virtual void set_debug_on_signal(int); - /// Turn on or off traceback on a signel. The default is on. + /// Turn on or off traceback on a signal. The default is on. virtual void set_traceback_on_signal(int); - /// Turn on or off exit after a signel. The default is on. + /// Turn on or off exit after a signal. The default is on. virtual void set_exit_on_signal(int); /** Turn on or off running an infinite loop after the debugger is started. This loop gives the debugger a chance to attack to the process. @@ -370,7 +370,7 @@ class Debugger { virtual void default_cmd(); /** Set the name of the executable for the current process. It is up to the programmer to set this, even if the Debugger - is initialized with the KeyVal constructor. */ + is initialized with the constructor. */ virtual void set_exec(const char *); /// Called when signal sig is received. This is mainly for internal use. @@ -381,12 +381,22 @@ class Debugger { /// Return the global default debugger. static std::shared_ptr default_debugger(); + /// Register a (one-time) action to be executed when debugger is launched + /// @param action an action to be executed + /// @note multiple actions registered via this will be executed in order of + /// their registration + void register_prelaunch_action(std::function action); + private: /// Replaces alias in cmd_ with its full form void resolve_cmd_alias(); + /// Replace macros (\c PID , \c EXEC , \c PREFIX ) in \p cmd by their values + /// \param cmd a string + /// \return processed str std::string replace_macros(std::string cmd); static const std::string gdb_cmd_; static const std::string lldb_cmd_; + std::vector> actions_; // prelaunch actions }; /// Use this to create a Debugger object and make it the default From 2f2df83870cd3e5f0449720512e08609851d7652 Mon Sep 17 00:00:00 2001 From: Samuel Powell Date: Mon, 16 Sep 2024 11:42:46 -0400 Subject: [PATCH 3/6] C-c, C-v --- src/TiledArray/util/bug.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TiledArray/util/bug.cpp b/src/TiledArray/util/bug.cpp index 57e96c162d..41121b52ca 100644 --- a/src/TiledArray/util/bug.cpp +++ b/src/TiledArray/util/bug.cpp @@ -243,7 +243,7 @@ void Debugger::debug(const char *reason) { system_retvalue = system(cmd.c_str()); } if (system_retvalue != 0) { - ExEnv::outn() << prefix_ + std::cout << prefix_ << "Failed debugger launch: system() did not succeed ..." << std::endl; } else { // call to system() succeeded From 99decc18f3c60a41e7877be8112bb664234cdf30 Mon Sep 17 00:00:00 2001 From: Samuel Powell Date: Wed, 18 Sep 2024 12:58:28 -0400 Subject: [PATCH 4/6] Omitted header include --- src/TiledArray/util/bug.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/TiledArray/util/bug.h b/src/TiledArray/util/bug.h index f2f284169a..38ae55198f 100644 --- a/src/TiledArray/util/bug.h +++ b/src/TiledArray/util/bug.h @@ -30,6 +30,7 @@ #include #include +#include #include #include #include From 31ade880cc894eb12e535a8f2209e44fcf7ff573 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Sun, 10 Nov 2024 12:55:46 -0500 Subject: [PATCH 5/6] bug.cpp: use std::{signal,system} --- src/TiledArray/util/bug.cpp | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/TiledArray/util/bug.cpp b/src/TiledArray/util/bug.cpp index 41121b52ca..0105635f37 100644 --- a/src/TiledArray/util/bug.cpp +++ b/src/TiledArray/util/bug.cpp @@ -105,14 +105,14 @@ static void handler(int sig) { void Debugger::handle(int sig) { if (sig >= NSIG) return; typedef void (*handler_type)(int); - signal(sig, (handler_type)handler); + std::signal(sig, (handler_type)handler); signals[sig] = this; mysigs_[sig] = 1; } void Debugger::release(int sig) { if (sig >= NSIG) return; - signal(sig, SIG_DFL); + std::signal(sig, SIG_DFL); signals[sig] = nullptr; mysigs_[sig] = 0; } @@ -231,7 +231,6 @@ void Debugger::debug(const char *reason) { std::cout << "no reason given"; std::cout << std::endl; - const std::string cmd = replace_macros(cmd_); // start the debugger // before starting the debugger de-register signal handler for SIGTRAP to @@ -240,13 +239,13 @@ void Debugger::debug(const char *reason) { int system_retvalue = 0; if (!cmd.empty()) { std::cout << prefix_ << "Debugger: starting \"" << cmd << "\"" << std::endl; - system_retvalue = system(cmd.c_str()); + system_retvalue = std::system(cmd.c_str()); } if (system_retvalue != 0) { std::cout << prefix_ - << "Failed debugger launch: system() did not succeed ..." - << std::endl; - } else { // call to system() succeeded + << "Failed debugger launch: system() did not succeed ..." + << std::endl; + } else { // call to system() succeeded // wait until the debugger is ready if (sleep_) { std::cout << prefix_ << "Debugger: sleeping " << sleep_ @@ -257,17 +256,17 @@ void Debugger::debug(const char *reason) { std::cout << prefix_ << "Debugger: waiting for the user ..."; if (cmd_.find(" gdb ") != std::string::npos || cmd_.find(" lldb ") != std::string::npos) { - std::cout << - " configure debugging session (set breakpoints/watchpoints, " - "etc.) then type 'c' to continue running"; + std::cout + << " configure debugging session (set breakpoints/watchpoints, " + "etc.) then type 'c' to continue running"; } else if (cmd.empty()) { - std::cout << " attach debugger to process " - << std::to_string(getpid()) + std::cout << " attach debugger to process " << std::to_string(getpid()) << " as follows:" << std::endl - << prefix_ << "Debugger: - if using gdb: " - << replace_macros(gdb_cmd_) << std::endl - << prefix_ << "Debugger: - if using lldb: " - << replace_macros(lldb_cmd_); + << prefix_ + << "Debugger: - if using gdb: " << replace_macros(gdb_cmd_) + << std::endl + << prefix_ + << "Debugger: - if using lldb: " << replace_macros(lldb_cmd_); } std::cout << std::endl; @@ -299,7 +298,7 @@ void Debugger::got_signal(int sig) { else signame = "UNKNOWN SIGNAL"; - for (auto const &action: actions_) { + for (auto const &action : actions_) { action(); } actions_.clear(); From b376b06b9f1301200de5ed0464feaf08ca2f16c0 Mon Sep 17 00:00:00 2001 From: Eduard Valeyev Date: Sun, 10 Nov 2024 13:02:24 -0500 Subject: [PATCH 6/6] bug.h: reformat --- src/TiledArray/util/bug.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/TiledArray/util/bug.h b/src/TiledArray/util/bug.h index 38ae55198f..5367497b62 100644 --- a/src/TiledArray/util/bug.h +++ b/src/TiledArray/util/bug.h @@ -395,9 +395,10 @@ class Debugger { /// \param cmd a string /// \return processed str std::string replace_macros(std::string cmd); + static const std::string gdb_cmd_; static const std::string lldb_cmd_; - std::vector> actions_; // prelaunch actions + std::vector> actions_; // prelaunch actions }; /// Use this to create a Debugger object and make it the default