mirror of
https://github.com/aljazceru/lightning.git
synced 2026-01-07 16:14:26 +01:00
plugin: Add a timeout to the getmanifest call
If the plugin fails to respond to we may end up hanging indefinitely, so we limit the time we're willing to wait to 10 seconds. Signed-off-by: Christian Decker <decker.christian@gmail.com>
This commit is contained in:
committed by
Rusty Russell
parent
9ce3e960ec
commit
dc4fb650dc
@@ -9,6 +9,7 @@
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <ccan/utf8/utf8.h>
|
||||
#include <common/memleak.h>
|
||||
#include <common/timeout.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <lightningd/json.h>
|
||||
@@ -19,6 +20,14 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* How many seconds may the plugin take to reply to the `getmanifest
|
||||
* call`? This is the maximum delay to `lightningd --help` and until
|
||||
* we can start the main `io_loop` to communicate with peers. If this
|
||||
* hangs we can't do much, so we put an upper bound on the time we're
|
||||
* willing to wait. Plugins shouldn't do any initialization in the
|
||||
* `getmanifest` call anyway, that's what `init `is for. */
|
||||
#define PLUGIN_MANIFEST_TIMEOUT 10
|
||||
|
||||
struct plugin {
|
||||
struct list_node list;
|
||||
|
||||
@@ -43,6 +52,10 @@ struct plugin {
|
||||
struct list_head plugin_opts;
|
||||
|
||||
const char **methods;
|
||||
|
||||
/* Timer to add a timeout to some plugin RPC calls. Used to
|
||||
* guarantee that `getmanifest` doesn't block indefinitely. */
|
||||
const struct oneshot *timeout_timer;
|
||||
};
|
||||
|
||||
struct plugin_request {
|
||||
@@ -73,6 +86,8 @@ struct plugins {
|
||||
|
||||
/* RPC interface to bind JSON-RPC methods to */
|
||||
struct jsonrpc *rpc;
|
||||
|
||||
struct timers timers;
|
||||
};
|
||||
|
||||
struct json_output {
|
||||
@@ -112,6 +127,7 @@ struct plugins *plugins_new(const tal_t *ctx, struct log_book *log_book,
|
||||
p->log_book = log_book;
|
||||
p->log = new_log(p, log_book, "plugin-manager");
|
||||
p->rpc = rpc;
|
||||
timers_init(&p->timers, time_mono());
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -618,6 +634,12 @@ static bool plugin_rpcmethods_add(const struct plugin_request *req)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void plugin_manifest_timeout(struct plugin *plugin)
|
||||
{
|
||||
log_broken(plugin->log, "The plugin failed to respond to \"getmanifest\" in time, terminating.");
|
||||
fatal("Can't recover from plugin failure, terminating.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for the plugin_manifest request.
|
||||
*/
|
||||
@@ -637,6 +659,8 @@ static void plugin_manifest_cb(const struct plugin_request *req, struct plugin *
|
||||
|
||||
if (!plugin_opts_add(req) || !plugin_rpcmethods_add(req))
|
||||
plugin_kill(plugin, "Failed to register options or methods");
|
||||
/* Reset timer, it'd kill us otherwise. */
|
||||
tal_free(plugin->timeout_timer);
|
||||
}
|
||||
|
||||
/* If this is a valid plugin return full path name, otherwise NULL */
|
||||
@@ -710,6 +734,7 @@ void plugins_init(struct plugins *plugins)
|
||||
struct plugin *p;
|
||||
char **cmd;
|
||||
int stdin, stdout;
|
||||
struct timer *expired;
|
||||
plugins->pending_manifests = 0;
|
||||
uintmap_init(&plugins->pending_requests);
|
||||
|
||||
@@ -735,10 +760,19 @@ void plugins_init(struct plugins *plugins)
|
||||
io_new_conn(p, stdin, plugin_stdin_conn_init, p);
|
||||
plugin_request_send(p, "getmanifest", "[]", plugin_manifest_cb, p);
|
||||
plugins->pending_manifests++;
|
||||
p->timeout_timer = new_reltimer(
|
||||
&plugins->timers, p, time_from_sec(PLUGIN_MANIFEST_TIMEOUT),
|
||||
plugin_manifest_timeout, p);
|
||||
tal_free(cmd);
|
||||
}
|
||||
if (plugins->pending_manifests > 0)
|
||||
io_loop(NULL, NULL);
|
||||
|
||||
while (plugins->pending_manifests > 0) {
|
||||
void *v = io_loop(&plugins->timers, &expired);
|
||||
if (v == plugins)
|
||||
break;
|
||||
if (expired)
|
||||
timer_expired(plugins, expired);
|
||||
}
|
||||
}
|
||||
|
||||
static void plugin_config_cb(const struct plugin_request *req,
|
||||
|
||||
Reference in New Issue
Block a user