Skip to content

Commit 87664ae

Browse files
authored
Merge pull request #473 from ValeevGroup/powellsr/fix/debug-attach-handling
Powellsr/fix/debug attach handling
2 parents fe6d848 + b376b06 commit 87664ae

File tree

2 files changed

+101
-66
lines changed

2 files changed

+101
-66
lines changed

src/TiledArray/util/bug.cpp

Lines changed: 81 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ Debugger::~Debugger() {
7777
for (int i = 0; i < NSIG; i++) {
7878
if (mysigs_[i]) signals[i] = nullptr;
7979
}
80-
delete[] mysigs_;
8180
}
8281

8382
void Debugger::init() {
@@ -91,7 +90,7 @@ void Debugger::init() {
9190
debug_ = 1;
9291
wait_for_debugger_ = 1;
9392

94-
mysigs_ = new int[NSIG];
93+
mysigs_ = std::make_unique<int[]>(NSIG);
9594
for (int i = 0; i < NSIG; i++) {
9695
mysigs_[i] = 0;
9796
}
@@ -106,14 +105,14 @@ static void handler(int sig) {
106105
void Debugger::handle(int sig) {
107106
if (sig >= NSIG) return;
108107
typedef void (*handler_type)(int);
109-
signal(sig, (handler_type)handler);
108+
std::signal(sig, (handler_type)handler);
110109
signals[sig] = this;
111110
mysigs_[sig] = 1;
112111
}
113112

114113
void Debugger::release(int sig) {
115114
if (sig >= NSIG) return;
116-
signal(sig, SIG_DFL);
115+
std::signal(sig, SIG_DFL);
117116
signals[sig] = nullptr;
118117
mysigs_[sig] = 0;
119118
}
@@ -180,25 +179,48 @@ void Debugger::default_cmd() {
180179
}
181180
}
182181

182+
const std::string Debugger::gdb_cmd_ =
183+
"gdb -ex \"set variable debugger_ready_=1\" --pid=$(PID) $(EXEC)";
184+
const std::string Debugger::lldb_cmd_ =
185+
"lldb -p $(PID) -o \"expr debugger_ready_=1\"";
186+
183187
void Debugger::resolve_cmd_alias() {
184188
if (cmd_ == "gdb_xterm") {
185-
cmd_ =
186-
"xterm -title \"$(PREFIX)$(EXEC)\" -e gdb -ex \"set variable "
187-
"debugger_ready_=1\" --pid=$(PID) $(EXEC) &";
189+
cmd_ = "xterm -title \"$(PREFIX)$(EXEC)\" -e " + gdb_cmd_ + " &";
188190
} else if (cmd_ == "lldb_xterm") {
189-
cmd_ =
190-
"xterm -title \"$(PREFIX)$(EXEC)\" -e lldb -p $(PID) -o \"expr "
191-
"debugger_ready_=1\" &";
191+
cmd_ = "xterm -title \"$(PREFIX)$(EXEC)\" -e " + lldb_cmd_ + " &";
192192
}
193193
}
194194

195+
std::string Debugger::replace_macros(std::string str) {
196+
if (!str.empty()) {
197+
int pid = getpid();
198+
std::string::size_type pos;
199+
std::string pidvar("$(PID)");
200+
while ((pos = str.find(pidvar)) != std::string::npos) {
201+
std::string pidstr;
202+
pidstr += std::to_string(pid);
203+
str.replace(pos, pidvar.size(), pidstr);
204+
}
205+
std::string execvar("$(EXEC)");
206+
while ((pos = str.find(execvar)) != std::string::npos) {
207+
str.replace(pos, execvar.size(), exec_);
208+
}
209+
std::string prefixvar("$(PREFIX)");
210+
while ((pos = str.find(prefixvar)) != std::string::npos) {
211+
str.replace(pos, prefixvar.size(), prefix_);
212+
}
213+
}
214+
return str;
215+
}
216+
195217
void Debugger::set_cmd(const char *cmd) {
196218
if (cmd) {
197219
cmd_ = cmd;
198-
resolve_cmd_alias();
199220
} else {
200221
cmd_.resize(0);
201222
}
223+
this->resolve_cmd_alias();
202224
}
203225

204226
void Debugger::debug(const char *reason) {
@@ -209,58 +231,48 @@ void Debugger::debug(const char *reason) {
209231
std::cout << "no reason given";
210232
std::cout << std::endl;
211233

212-
if (!cmd_.empty()) {
213-
int pid = getpid();
214-
// contruct the command name
215-
std::string cmd = cmd_;
216-
std::string::size_type pos;
217-
std::string pidvar("$(PID)");
218-
while ((pos = cmd.find(pidvar)) != std::string::npos) {
219-
std::string pidstr;
220-
pidstr += std::to_string(pid);
221-
cmd.replace(pos, pidvar.size(), pidstr);
222-
}
223-
std::string execvar("$(EXEC)");
224-
while ((pos = cmd.find(execvar)) != std::string::npos) {
225-
cmd.replace(pos, execvar.size(), exec_);
226-
}
227-
std::string prefixvar("$(PREFIX)");
228-
while ((pos = cmd.find(prefixvar)) != std::string::npos) {
229-
cmd.replace(pos, prefixvar.size(), prefix_);
230-
}
231-
232-
// start the debugger
233-
// before starting the debugger de-register signal handler for SIGTRAP to
234-
// let the debugger take over
235-
release(SIGTRAP);
234+
const std::string cmd = replace_macros(cmd_);
235+
// start the debugger
236+
// before starting the debugger de-register signal handler for SIGTRAP to
237+
// let the debugger take over
238+
release(SIGTRAP);
239+
int system_retvalue = 0;
240+
if (!cmd.empty()) {
236241
std::cout << prefix_ << "Debugger: starting \"" << cmd << "\"" << std::endl;
237-
debugger_ready_ = 0;
238-
const auto system_retvalue = system(cmd.c_str());
239-
if (system_retvalue != 0) { // call to system() failed
240-
std::cout << prefix_
241-
<< "Failed debugger launch: system() did not succeed ..."
242-
<< std::endl;
243-
} else { // call to system() succeeded
244-
// wait until the debugger is ready
245-
if (sleep_) {
246-
std::cout << prefix_ << "Sleeping " << sleep_
247-
<< " seconds to wait for debugger ..." << std::endl;
248-
sleep(sleep_);
249-
}
250-
if (wait_for_debugger_) {
251-
std::string make_ready_message;
252-
if (cmd_.find(" gdb ") != std::string::npos ||
253-
cmd_.find(" lldb ") != std::string::npos) {
254-
make_ready_message =
255-
" configure debugging session (set breakpoints/watchpoints, "
256-
"etc.) then type 'c' to continue running";
257-
}
258-
259-
std::cout << prefix_ << ": waiting for the user ..."
260-
<< make_ready_message << std::endl;
261-
while (!debugger_ready_)
262-
;
242+
system_retvalue = std::system(cmd.c_str());
243+
}
244+
if (system_retvalue != 0) {
245+
std::cout << prefix_
246+
<< "Failed debugger launch: system() did not succeed ..."
247+
<< std::endl;
248+
} else { // call to system() succeeded
249+
// wait until the debugger is ready
250+
if (sleep_) {
251+
std::cout << prefix_ << "Debugger: sleeping " << sleep_
252+
<< " seconds to wait for debugger ..." << std::endl;
253+
sleep(sleep_);
254+
}
255+
if (wait_for_debugger_) {
256+
std::cout << prefix_ << "Debugger: waiting for the user ...";
257+
if (cmd_.find(" gdb ") != std::string::npos ||
258+
cmd_.find(" lldb ") != std::string::npos) {
259+
std::cout
260+
<< " configure debugging session (set breakpoints/watchpoints, "
261+
"etc.) then type 'c' to continue running";
262+
} else if (cmd.empty()) {
263+
std::cout << " attach debugger to process " << std::to_string(getpid())
264+
<< " as follows:" << std::endl
265+
<< prefix_
266+
<< "Debugger: - if using gdb: " << replace_macros(gdb_cmd_)
267+
<< std::endl
268+
<< prefix_
269+
<< "Debugger: - if using lldb: " << replace_macros(lldb_cmd_);
263270
}
271+
std::cout << std::endl;
272+
273+
debugger_ready_ = 0;
274+
while (!debugger_ready_)
275+
;
264276
}
265277
}
266278
}
@@ -286,6 +298,10 @@ void Debugger::got_signal(int sig) {
286298
else
287299
signame = "UNKNOWN SIGNAL";
288300

301+
for (auto const &action : actions_) {
302+
action();
303+
}
304+
actions_.clear();
289305
if (traceback_) {
290306
traceback(signame);
291307
}
@@ -355,6 +371,10 @@ void Debugger::__traceback(const std::string &prefix, const char *reason) {
355371
std::cout << result.str(nframes_to_skip) << std::endl;
356372
}
357373

374+
void Debugger::register_prelaunch_action(std::function<void()> action) {
375+
actions_.push_back(action);
376+
}
377+
358378
void create_debugger(const char *cmd, const char *exec, std::int64_t rank) {
359379
auto debugger = std::make_shared<TiledArray::Debugger>();
360380
if (cmd) debugger->set_cmd(cmd);

src/TiledArray/util/bug.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#include <cassert>
3232
#include <cstdint>
33+
#include <functional>
3334
#include <memory>
3435
#include <string>
3536
#include <unordered_map>
@@ -291,7 +292,7 @@ class Debugger {
291292
bool sleep_;
292293
bool wait_for_debugger_;
293294
bool handle_sigint_;
294-
int *mysigs_;
295+
std::unique_ptr<int[]> mysigs_;
295296

296297
void init();
297298

@@ -325,11 +326,11 @@ class Debugger {
325326
@param reason optional string specifying the reason for traceback
326327
*/
327328
virtual void traceback(const char *reason);
328-
/// Turn on or off debugging on a signel. The default is on.
329+
/// Turn on or off debugging on a signal. The default is on.
329330
virtual void set_debug_on_signal(int);
330-
/// Turn on or off traceback on a signel. The default is on.
331+
/// Turn on or off traceback on a signal. The default is on.
331332
virtual void set_traceback_on_signal(int);
332-
/// Turn on or off exit after a signel. The default is on.
333+
/// Turn on or off exit after a signal. The default is on.
333334
virtual void set_exit_on_signal(int);
334335
/** Turn on or off running an infinite loop after the debugger is started.
335336
This loop gives the debugger a chance to attack to the process.
@@ -370,7 +371,7 @@ class Debugger {
370371
virtual void default_cmd();
371372
/** Set the name of the executable for the current process.
372373
It is up to the programmer to set this, even if the Debugger
373-
is initialized with the KeyVal constructor. */
374+
is initialized with the constructor. */
374375
virtual void set_exec(const char *);
375376

376377
/// Called when signal sig is received. This is mainly for internal use.
@@ -381,9 +382,23 @@ class Debugger {
381382
/// Return the global default debugger.
382383
static std::shared_ptr<Debugger> default_debugger();
383384

385+
/// Register a (one-time) action to be executed when debugger is launched
386+
/// @param action an action to be executed
387+
/// @note multiple actions registered via this will be executed in order of
388+
/// their registration
389+
void register_prelaunch_action(std::function<void()> action);
390+
384391
private:
385392
/// Replaces alias in cmd_ with its full form
386393
void resolve_cmd_alias();
394+
/// Replace macros (\c PID , \c EXEC , \c PREFIX ) in \p cmd by their values
395+
/// \param cmd a string
396+
/// \return processed str
397+
std::string replace_macros(std::string cmd);
398+
399+
static const std::string gdb_cmd_;
400+
static const std::string lldb_cmd_;
401+
std::vector<std::function<void()>> actions_; // prelaunch actions
387402
};
388403

389404
/// Use this to create a Debugger object and make it the default

0 commit comments

Comments
 (0)