@@ -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+
992997static 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
10431060struct 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
16801707static void destroy_plugin_timer (struct plugin_timer * timer , struct plugin * p )
0 commit comments