Skip to content

Commit 392bc7f

Browse files
committed
libplugin: check that command has/hasn't terminated when we get pending/complete.
Signed-off-by: Rusty Russell <[email protected]>
1 parent c0fc8cc commit 392bc7f

File tree

1 file changed

+29
-2
lines changed

1 file changed

+29
-2
lines changed

plugins/libplugin.c

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -989,11 +989,17 @@ struct command_result *jsonrpc_get_datastore_(struct plugin *plugin,
989989
return send_outreq(plugin, req);
990990
}
991991

992+
static void destroy_cmd_mark_freed(struct command *cmd, bool *cmd_freed)
993+
{
994+
*cmd_freed = true;
995+
}
996+
992997
static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks)
993998
{
994999
const jsmntok_t *idtok, *contenttok;
9951000
struct out_req *out;
9961001
struct command_result *res;
1002+
bool cmd_freed;
9971003
const char *buf = plugin->rpc_buffer + plugin->rpc_read_offset;
9981004

9991005
idtok = json_get_member(buf, toks, "id");
@@ -1018,6 +1024,10 @@ static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks)
10181024
/* We want to free this if callback doesn't. */
10191025
tal_steal(tmpctx, out);
10201026

1027+
/* If they return complete, cmd should have been freed! */
1028+
cmd_freed = false;
1029+
tal_add_destructor2(out->cmd, destroy_cmd_mark_freed, &cmd_freed);
1030+
10211031
contenttok = json_get_member(buf, toks, "error");
10221032
if (contenttok) {
10231033
if (out->errcb)
@@ -1037,7 +1047,14 @@ static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks)
10371047
res = out->cb(out->cmd, buf, toks, out->arg);
10381048
}
10391049

1040-
assert(res == &pending || res == &complete);
1050+
if (res == &complete) {
1051+
assert(cmd_freed);
1052+
} else {
1053+
assert(res == &pending);
1054+
assert(!cmd_freed);
1055+
tal_del_destructor2(out->cmd, destroy_cmd_mark_freed,
1056+
&cmd_freed);
1057+
}
10411058
}
10421059

10431060
struct command_result *
@@ -1669,12 +1686,22 @@ static void call_plugin_timer(struct plugin *p, struct timer *timer)
16691686
struct plugin_timer *t = container_of(timer, struct plugin_timer, timer);
16701687
struct command *timer_cmd;
16711688
struct command_result *res;
1689+
bool cmd_freed = false;
16721690

16731691
/* This *isn't* owned by timer, which is owned by original command,
16741692
* since they may free that in callback */
16751693
timer_cmd = new_command(p, p, t->id, "timer", COMMAND_TYPE_TIMER);
1694+
tal_add_destructor2(timer_cmd, destroy_cmd_mark_freed, &cmd_freed);
1695+
16761696
res = t->cb(timer_cmd, t->cb_arg);
1677-
assert(res == &pending || res == &complete);
1697+
if (res == &pending) {
1698+
assert(!cmd_freed);
1699+
tal_del_destructor2(timer_cmd, destroy_cmd_mark_freed,
1700+
&cmd_freed);
1701+
} else {
1702+
assert(res == &complete);
1703+
assert(cmd_freed);
1704+
}
16781705
}
16791706

16801707
static void destroy_plugin_timer(struct plugin_timer *timer, struct plugin *p)

0 commit comments

Comments
 (0)