mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-03 10:46:58 +01:00
plugins: allow --dev-debugger=<pluginname>.
This currently just invokes GDB, but we could generalize it (though pdb doesn't allow attaching to a running process, other python debuggers seem to). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
b484933b40
commit
6323cc1898
11 changed files with 60 additions and 34 deletions
|
@ -4,6 +4,7 @@
|
|||
#include <ccan/err/err.h>
|
||||
#include <ccan/io/io.h>
|
||||
#include <ccan/str/str.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/daemon.h>
|
||||
#include <common/memleak.h>
|
||||
#include <common/status.h>
|
||||
|
@ -150,3 +151,23 @@ void daemon_shutdown(void)
|
|||
tal_free(tmpctx);
|
||||
wally_cleanup(0);
|
||||
}
|
||||
|
||||
void daemon_maybe_debug(int argc, char *argv[])
|
||||
{
|
||||
#if DEVELOPER
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (!streq(argv[i], "--debugger"))
|
||||
continue;
|
||||
|
||||
/* Don't let this mess up stdout, so redir to /dev/null */
|
||||
char *cmd = tal_fmt(NULL, "${DEBUG_TERM:-gnome-terminal --} gdb -ex 'attach %u' %s >/dev/null &", getpid(), argv[0]);
|
||||
fprintf(stderr, "Running %s\n", cmd);
|
||||
/* warn_unused_result is fascist bullshit.
|
||||
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 */
|
||||
if (system(cmd))
|
||||
;
|
||||
/* Continue in the debugger. */
|
||||
kill(getpid(), SIGSTOP);
|
||||
}
|
||||
#endif /* DEVELOPER */
|
||||
}
|
||||
|
|
|
@ -14,6 +14,9 @@ int daemon_poll(struct pollfd *fds, nfds_t nfds, int timeout);
|
|||
/* Shutdown for a valgrind-clean exit (frees everything) */
|
||||
void daemon_shutdown(void);
|
||||
|
||||
/* Kick in a debugger if they set --debugger */
|
||||
void daemon_maybe_debug(int argc, char *argv[]);
|
||||
|
||||
struct backtrace_state *backtrace_state;
|
||||
|
||||
#endif /* LIGHTNING_COMMON_DAEMON_H */
|
||||
|
|
|
@ -37,19 +37,10 @@ void subdaemon_setup(int argc, char *argv[])
|
|||
logging_io = true;
|
||||
}
|
||||
|
||||
daemon_maybe_debug(argc, argv);
|
||||
|
||||
#if DEVELOPER
|
||||
/* From debugger, set debugger_spin to 0. */
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (streq(argv[i], "--debugger")) {
|
||||
char *cmd = tal_fmt(NULL, "${DEBUG_TERM:-gnome-terminal --} gdb -ex 'attach %u' %s &", getpid(), argv[0]);
|
||||
fprintf(stderr, "Running %s\n", cmd);
|
||||
/* warn_unused_result is fascist bullshit.
|
||||
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 */
|
||||
if (system(cmd))
|
||||
;
|
||||
/* Continue in the debugger. */
|
||||
kill(getpid(), SIGSTOP);
|
||||
}
|
||||
if (strstarts(argv[i], "--dev-disconnect=")) {
|
||||
dev_disconnect_init(atoi(argv[i]
|
||||
+ strlen("--dev-disconnect=")));
|
||||
|
|
|
@ -110,8 +110,8 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
|
|||
* is a nod to keeping it minimal and explicit: we need this code for
|
||||
* testing, but its existence means we're not actually testing the
|
||||
* same exact code users will be running. */
|
||||
ld->dev_debug_subprocess = NULL;
|
||||
#if DEVELOPER
|
||||
ld->dev_debug_subdaemon = NULL;
|
||||
ld->dev_disconnect_fd = -1;
|
||||
ld->dev_subdaemon_fail = false;
|
||||
ld->dev_allow_localhost = false;
|
||||
|
@ -611,7 +611,7 @@ int main(int argc, char *argv[])
|
|||
/*~ Initialize all the plugins we just registered, so they can
|
||||
* do their thing and tell us about themselves (including
|
||||
* options registration). */
|
||||
plugins_init(ld->plugins);
|
||||
plugins_init(ld->plugins, ld->dev_debug_subprocess);
|
||||
|
||||
/*~ Handle options and config; move to .lightningd (--lightning-dir) */
|
||||
handle_opts(ld, argc, argv);
|
||||
|
|
|
@ -183,10 +183,10 @@ struct lightningd {
|
|||
* if we are the fundee. */
|
||||
u32 max_funding_unconfirmed;
|
||||
|
||||
#if DEVELOPER
|
||||
/* If we want to debug a subdaemon. */
|
||||
const char *dev_debug_subdaemon;
|
||||
/* If we want to debug a subdaemon/plugin. */
|
||||
const char *dev_debug_subprocess;
|
||||
|
||||
#if DEVELOPER
|
||||
/* If we have a --dev-disconnect file */
|
||||
int dev_disconnect_fd;
|
||||
|
||||
|
|
|
@ -435,6 +435,12 @@ static void config_register_opts(struct lightningd *ld)
|
|||
}
|
||||
|
||||
#if DEVELOPER
|
||||
static char *opt_subprocess_debug(const char *optarg, struct lightningd *ld)
|
||||
{
|
||||
ld->dev_debug_subprocess = optarg;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void dev_register_opts(struct lightningd *ld)
|
||||
{
|
||||
opt_register_noarg("--dev-no-reconnect", opt_set_invbool,
|
||||
|
@ -442,8 +448,8 @@ static void dev_register_opts(struct lightningd *ld)
|
|||
"Disable automatic reconnect attempts");
|
||||
opt_register_noarg("--dev-fail-on-subdaemon-fail", opt_set_bool,
|
||||
&ld->dev_subdaemon_fail, opt_hidden);
|
||||
opt_register_arg("--dev-debugger=<subdaemon>", opt_subd_debug, NULL,
|
||||
ld, "Invoke gdb at start of <subdaemon>");
|
||||
opt_register_early_arg("--dev-debugger=<subprocess>", opt_subprocess_debug, NULL,
|
||||
ld, "Invoke gdb at start of <subprocess>");
|
||||
opt_register_arg("--dev-broadcast-interval=<ms>", opt_set_uintval,
|
||||
opt_show_uintval, &ld->config.broadcast_interval_msec,
|
||||
"Time between gossip broadcasts in milliseconds");
|
||||
|
|
|
@ -766,7 +766,7 @@ void clear_plugins(struct plugins *plugins)
|
|||
tal_free(p);
|
||||
}
|
||||
|
||||
void plugins_init(struct plugins *plugins)
|
||||
void plugins_init(struct plugins *plugins, const char *dev_plugin_debug)
|
||||
{
|
||||
struct plugin *p;
|
||||
char **cmd;
|
||||
|
@ -778,9 +778,13 @@ void plugins_init(struct plugins *plugins)
|
|||
|
||||
/* Spawn the plugin processes before entering the io_loop */
|
||||
list_for_each(&plugins->plugins, p, list) {
|
||||
cmd = tal_arr(p, char *, 2);
|
||||
bool debug;
|
||||
|
||||
debug = dev_plugin_debug && strends(p->cmd, dev_plugin_debug);
|
||||
cmd = tal_arrz(p, char *, 2 + debug);
|
||||
cmd[0] = p->cmd;
|
||||
cmd[1] = NULL;
|
||||
if (debug)
|
||||
cmd[1] = "--debugger";
|
||||
p->pid = pipecmdarr(&stdout, &stdin, NULL, cmd);
|
||||
|
||||
if (p->pid == -1)
|
||||
|
@ -798,9 +802,15 @@ void plugins_init(struct plugins *plugins)
|
|||
json_array_end(req->stream);
|
||||
plugin_request_queue(req);
|
||||
plugins->pending_manifests++;
|
||||
p->timeout_timer = new_reltimer(
|
||||
&plugins->timers, p, time_from_sec(PLUGIN_MANIFEST_TIMEOUT),
|
||||
plugin_manifest_timeout, p);
|
||||
/* Don't timeout if they're running a debugger. */
|
||||
if (debug)
|
||||
p->timeout_timer = NULL;
|
||||
else {
|
||||
p->timeout_timer
|
||||
= new_reltimer(&plugins->timers, p,
|
||||
time_from_sec(PLUGIN_MANIFEST_TIMEOUT),
|
||||
plugin_manifest_timeout, p);
|
||||
}
|
||||
tal_free(cmd);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,8 +27,10 @@ struct plugins *plugins_new(const tal_t *ctx, struct log_book *log_book,
|
|||
* arguments. In order to read the getmanifest reply from the plugins
|
||||
* we spin up our own io_loop that exits once all plugins have
|
||||
* responded.
|
||||
*
|
||||
* The dev_plugin_debug arg comes from --dev-debugger if DEVELOPER.
|
||||
*/
|
||||
void plugins_init(struct plugins *plugins);
|
||||
void plugins_init(struct plugins *plugins, const char *dev_plugin_debug);
|
||||
|
||||
/**
|
||||
* Register a plugin for initialization and execution.
|
||||
|
|
|
@ -626,7 +626,7 @@ static struct subd *new_subd(struct lightningd *ld,
|
|||
assert(name != NULL);
|
||||
|
||||
#if DEVELOPER
|
||||
debug_subd = ld->dev_debug_subdaemon;
|
||||
debug_subd = ld->dev_debug_subprocess;
|
||||
disconnect_fd = ld->dev_disconnect_fd;
|
||||
#endif /* DEVELOPER */
|
||||
|
||||
|
@ -784,12 +784,6 @@ void subd_release_channel(struct subd *owner, void *channel)
|
|||
}
|
||||
|
||||
#if DEVELOPER
|
||||
char *opt_subd_debug(const char *optarg, struct lightningd *ld)
|
||||
{
|
||||
ld->dev_debug_subdaemon = optarg;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *opt_subd_dev_disconnect(const char *optarg, struct lightningd *ld)
|
||||
{
|
||||
ld->dev_disconnect_fd = open(optarg, O_RDONLY);
|
||||
|
|
|
@ -206,7 +206,6 @@ void subd_shutdown(struct subd *subd, unsigned int seconds);
|
|||
const char *find_my_abspath(const tal_t *ctx, const char *argv0);
|
||||
|
||||
#if DEVELOPER
|
||||
char *opt_subd_debug(const char *optarg, struct lightningd *ld);
|
||||
char *opt_subd_dev_disconnect(const char *optarg, struct lightningd *ld);
|
||||
|
||||
bool dev_disconnect_permanent(struct lightningd *ld);
|
||||
|
|
|
@ -136,7 +136,7 @@ void onchaind_replay_channels(struct lightningd *ld UNNEEDED)
|
|||
void plugins_config(struct plugins *plugins UNNEEDED)
|
||||
{ fprintf(stderr, "plugins_config called!\n"); abort(); }
|
||||
/* Generated stub for plugins_init */
|
||||
void plugins_init(struct plugins *plugins UNNEEDED)
|
||||
void plugins_init(struct plugins *plugins UNNEEDED, const char *dev_plugin_debug UNNEEDED)
|
||||
{ fprintf(stderr, "plugins_init called!\n"); abort(); }
|
||||
/* Generated stub for plugins_new */
|
||||
struct plugins *plugins_new(const tal_t *ctx UNNEEDED, struct log_book *log_book UNNEEDED,
|
||||
|
|
Loading…
Add table
Reference in a new issue