lightningd: simplify memleak code.

Instead of doing this weird chaining, just call them all at once and
use a reference counter.

To make it simpler, we return the subd_req so we can hang a destructor
off it which decrements after the request is complete.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2022-03-08 10:44:41 +10:30
parent 0c4cc782df
commit 00bb6f07d7
10 changed files with 168 additions and 288 deletions

View File

@ -124,14 +124,14 @@ static void json_add_backtrace(struct json_stream *response,
json_array_end(response);
}
static void scan_mem(struct command *cmd,
struct json_stream *response,
struct lightningd *ld,
const struct subd *leaking_subd)
static void finish_report(const struct leak_detect *leaks)
{
struct htable *memtable;
const tal_t *i;
const uintptr_t *backtrace;
struct command *cmd = leaks->cmd;
struct lightningd *ld = cmd->ld;
struct json_stream *response = json_stream_success(cmd);
/* Enter everything, except this cmd and its jcon */
memtable = memleak_find_allocations(cmd, cmd, cmd->jcon);
@ -165,126 +165,67 @@ static void scan_mem(struct command *cmd,
json_object_end(response);
}
if (leaking_subd) {
for (size_t i = 0; i < tal_count(leaks->leakers); i++) {
json_object_start(response, NULL);
json_add_string(response, "subdaemon", leaking_subd->name);
json_add_string(response, "subdaemon", leaks->leakers[i]);
json_object_end(response);
}
json_array_end(response);
/* Command is now done. */
was_pending(command_success(cmd, response));
}
struct leak_info {
struct command *cmd;
struct subd *leaker;
};
static void report_leak_info2(struct leak_info *leak_info)
static void leak_detect_req_done(const struct subd_req *req,
struct leak_detect *leak_detect)
{
struct json_stream *response = json_stream_success(leak_info->cmd);
scan_mem(leak_info->cmd, response, leak_info->cmd->ld, leak_info->leaker);
was_pending(command_success(leak_info->cmd, response));
leak_detect->num_outstanding_requests--;
if (leak_detect->num_outstanding_requests == 0)
finish_report(leak_detect);
}
static void report_leak_info(struct command *cmd, struct subd *leaker)
/* Start a leak request: decrements num_outstanding_requests when freed. */
void start_leak_request(const struct subd_req *req,
struct leak_detect *leak_detect)
{
struct leak_info *leak_info = tal(cmd, struct leak_info);
leak_detect->num_outstanding_requests++;
/* When req is freed, request finished. */
tal_add_destructor2(req, leak_detect_req_done, leak_detect);
}
leak_info->cmd = cmd;
leak_info->leaker = leaker;
/* Leak detection in a reply handler thinks we're leaking conn. */
notleak(new_reltimer(leak_info->cmd->ld->timers, leak_info->cmd,
time_from_sec(0),
report_leak_info2, leak_info));
/* Yep, found a leak in this subd. */
void report_subd_memleak(struct leak_detect *leak_detect, struct subd *leaker)
{
tal_arr_expand(&leak_detect->leakers,
tal_strdup(leak_detect, leaker->name));
}
static void gossip_dev_memleak_done(struct subd *gossipd,
const u8 *reply,
const int *fds UNUSED,
struct command *cmd)
struct leak_detect *leaks)
{
bool found_leak;
if (!fromwire_gossipd_dev_memleak_reply(reply, &found_leak)) {
was_pending(command_fail(cmd, LIGHTNINGD,
"Bad gossip_dev_memleak"));
return;
}
if (!fromwire_gossipd_dev_memleak_reply(reply, &found_leak))
fatal("Bad gossip_dev_memleak");
report_leak_info(cmd, found_leak ? gossipd : NULL);
if (found_leak)
report_subd_memleak(leaks, gossipd);
}
static void connect_dev_memleak_done(struct subd *connectd,
const u8 *reply,
const int *fds UNUSED,
struct command *cmd)
struct leak_detect *leaks)
{
bool found_leak;
if (!fromwire_connectd_dev_memleak_reply(reply, &found_leak)) {
was_pending(command_fail(cmd, LIGHTNINGD,
"Bad connect_dev_memleak"));
return;
}
if (!fromwire_connectd_dev_memleak_reply(reply, &found_leak))
fatal("Bad connect_dev_memleak");
if (found_leak) {
report_leak_info(cmd, connectd);
return;
}
/* No leak? Ask openingd. */
opening_dev_memleak(cmd);
}
static void hsm_dev_memleak_done(struct subd *hsmd,
const u8 *reply,
struct command *cmd)
{
struct lightningd *ld = cmd->ld;
bool found_leak;
if (!fromwire_hsmd_dev_memleak_reply(reply, &found_leak)) {
was_pending(command_fail(cmd, LIGHTNINGD,
"Bad hsm_dev_memleak"));
return;
}
if (found_leak) {
report_leak_info(cmd, hsmd);
return;
}
/* No leak? Ask gossipd. */
subd_req(ld->gossip, ld->gossip, take(towire_gossipd_dev_memleak(NULL)),
-1, 0, gossip_dev_memleak_done, cmd);
}
void peer_memleak_done(struct command *cmd, struct subd *leaker)
{
if (leaker)
report_leak_info(cmd, leaker);
else {
/* No leak there, try hsmd (we talk to hsm sync) */
u8 *msg = towire_hsmd_dev_memleak(NULL);
if (!wire_sync_write(cmd->ld->hsm_fd, take(msg)))
fatal("Could not write to HSM: %s", strerror(errno));
hsm_dev_memleak_done(cmd->ld->hsm,
wire_sync_read(tmpctx, cmd->ld->hsm_fd),
cmd);
}
}
void opening_memleak_done(struct command *cmd, struct subd *leaker)
{
if (leaker)
report_leak_info(cmd, leaker);
else {
/* No leak there, try normal peers. */
peer_dev_memleak(cmd);
}
if (found_leak)
report_subd_memleak(leaks, connectd);
}
static struct command_result *json_memleak(struct command *cmd,
@ -293,6 +234,9 @@ static struct command_result *json_memleak(struct command *cmd,
const jsmntok_t *params)
{
struct lightningd *ld = cmd->ld;
u8 *msg;
bool found_leak;
struct leak_detect *leaks;
if (!param(cmd, buffer, params, NULL))
return command_param_failed();
@ -302,11 +246,34 @@ static struct command_result *json_memleak(struct command *cmd,
"Leak detection needs $LIGHTNINGD_DEV_MEMLEAK");
}
/* Start by asking connectd, which is always async. */
subd_req(ld->connectd, ld->connectd,
take(towire_connectd_dev_memleak(NULL)),
-1, 0, connect_dev_memleak_done, cmd);
leaks = tal(cmd, struct leak_detect);
leaks->cmd = cmd;
leaks->num_outstanding_requests = 0;
leaks->leakers = tal_arr(leaks, const char *, 0);
/* hsmd is sync, so do that first. */
if (!wire_sync_write(ld->hsm_fd,
take(towire_hsmd_dev_memleak(NULL))))
fatal("Could not write to HSM: %s", strerror(errno));
msg = wire_sync_read(tmpctx, ld->hsm_fd);
if (!fromwire_hsmd_dev_memleak_reply(msg, &found_leak))
fatal("Bad HSMD_DEV_MEMLEAK_REPLY: %s", tal_hex(tmpctx, msg));
if (found_leak)
report_subd_memleak(leaks, ld->hsm);
/* Now do all the async ones. */
start_leak_request(subd_req(ld->connectd, ld->connectd,
take(towire_connectd_dev_memleak(NULL)),
-1, 0, connect_dev_memleak_done, leaks),
leaks);
start_leak_request(subd_req(ld->gossip, ld->gossip,
take(towire_gossipd_dev_memleak(NULL)),
-1, 0, gossip_dev_memleak_done, leaks),
leaks);
/* Ask all per-peer daemons */
peer_dev_memleak(ld, leaks);
return command_still_pending(cmd);
}

View File

@ -3,11 +3,20 @@
#include "config.h"
struct command;
struct htable;
struct strmap;
struct subd;
struct subd_req;
void opening_memleak_done(struct command *cmd, struct subd *leaker);
void peer_memleak_done(struct command *cmd, struct subd *leaker);
struct leak_detect {
struct command *cmd;
size_t num_outstanding_requests;
const char **leakers;
};
/* Start a leak request: decrements num_outstanding_requests when freed. */
void start_leak_request(const struct subd_req *req,
struct leak_detect *leak_detect);
/* Yep, found a leak in this subd. */
void report_subd_memleak(struct leak_detect *leak_detect, struct subd *leaker);
#endif /* LIGHTNING_LIGHTNINGD_MEMDUMP_H */

View File

@ -201,89 +201,3 @@ void handle_reestablish(struct lightningd *ld,
tal_free(peer_fd);
}
}
#if DEVELOPER
/* Indented to avoid include ordering check */
#include <lightningd/memdump.h>
static void opening_died_forget_memleak(struct subd *open_daemon,
struct command *cmd)
{
/* FIXME: We ignore the remaining opening daemons in this case. */
opening_memleak_done(cmd, NULL);
}
/* Mutual recursion */
static void opening_memleak_req_next(struct command *cmd, struct peer *prev);
static void opening_memleak_req_done(struct subd *open_daemon,
const u8 *msg, const int *fds UNUSED,
struct command *cmd)
{
bool found_leak;
struct peer *p;
p = ((struct uncommitted_channel *)open_daemon->channel)->peer;
tal_del_destructor2(open_daemon, opening_died_forget_memleak, cmd);
if (!fromwire_openingd_dev_memleak_reply(msg, &found_leak)) {
was_pending(command_fail(cmd, LIGHTNINGD,
"Bad opening_dev_memleak"));
return;
}
if (found_leak) {
opening_memleak_done(cmd, open_daemon);
return;
}
opening_memleak_req_next(cmd, p);
}
static void opening_memleak_req_next(struct command *cmd, struct peer *prev)
{
struct peer *p;
struct channel *c;
u8 *msg;
list_for_each(&cmd->ld->peers, p, list) {
struct subd *open_daemon;
c = NULL;
if (!p->uncommitted_channel
&& !(c = peer_unsaved_channel(p)))
continue;
if (p == prev) {
prev = NULL;
continue;
}
if (prev != NULL)
continue;
if (c)
open_daemon = c->owner;
else
open_daemon = p->uncommitted_channel->open_daemon;
if (!open_daemon)
continue;
/* FIXME: dualopend doesn't support memleak when we ask */
if (streq(open_daemon->name, "dualopend"))
continue;
msg = towire_openingd_dev_memleak(NULL);
subd_req(p, open_daemon, take(msg), -1, 0,
opening_memleak_req_done, cmd);
/* Just in case it dies before replying! */
tal_add_destructor2(open_daemon,
opening_died_forget_memleak, cmd);
return;
}
opening_memleak_done(cmd, NULL);
}
void opening_dev_memleak(struct command *cmd)
{
opening_memleak_req_next(cmd, NULL);
}
#endif /* DEVELOPER */

View File

@ -127,10 +127,4 @@ void handle_reestablish(struct lightningd *ld,
const u8 *reestablish,
struct peer_fd *peer_fd);
#if DEVELOPER
struct command;
/* Calls report_leak_info() async. */
void opening_dev_memleak(struct command *cmd);
#endif
#endif /* LIGHTNING_LIGHTNINGD_OPENING_COMMON_H */

View File

@ -62,6 +62,7 @@
#include <lightningd/subd.h>
#include <limits.h>
#include <onchaind/onchaind_wiregen.h>
#include <openingd/openingd_wiregen.h>
#include <stdlib.h>
#include <unistd.h>
#include <wally_bip32.h>
@ -2323,104 +2324,76 @@ static const struct json_command dev_forget_channel_command = {
};
AUTODATA(json_command, &dev_forget_channel_command);
static void subd_died_forget_memleak(struct subd *openingd, struct command *cmd)
{
/* FIXME: We ignore the remaining per-peer daemons in this case. */
peer_memleak_done(cmd, NULL);
}
/* Mutual recursion */
static void peer_memleak_req_next(struct command *cmd, struct channel *prev);
static void peer_memleak_req_done(struct subd *subd, bool found_leak,
struct command *cmd)
{
struct channel *c = subd->channel;
if (found_leak)
peer_memleak_done(cmd, subd);
else
peer_memleak_req_next(cmd, c);
}
static void channeld_memleak_req_done(struct subd *channeld,
const u8 *msg, const int *fds UNUSED,
struct command *cmd)
struct leak_detect *leaks)
{
bool found_leak;
tal_del_destructor2(channeld, subd_died_forget_memleak, cmd);
if (!fromwire_channeld_dev_memleak_reply(msg, &found_leak)) {
was_pending(command_fail(cmd, LIGHTNINGD,
"Bad channel_dev_memleak"));
return;
}
peer_memleak_req_done(channeld, found_leak, cmd);
if (!fromwire_channeld_dev_memleak_reply(msg, &found_leak))
fatal("Bad channel_dev_memleak");
if (found_leak)
report_subd_memleak(leaks, channeld);
}
static void onchaind_memleak_req_done(struct subd *onchaind,
const u8 *msg, const int *fds UNUSED,
struct command *cmd)
struct leak_detect *leaks)
{
bool found_leak;
tal_del_destructor2(onchaind, subd_died_forget_memleak, cmd);
if (!fromwire_onchaind_dev_memleak_reply(msg, &found_leak)) {
was_pending(command_fail(cmd, LIGHTNINGD,
"Bad onchain_dev_memleak"));
return;
}
peer_memleak_req_done(onchaind, found_leak, cmd);
if (!fromwire_onchaind_dev_memleak_reply(msg, &found_leak))
fatal("Bad onchaind_dev_memleak");
if (found_leak)
report_subd_memleak(leaks, onchaind);
}
static void peer_memleak_req_next(struct command *cmd, struct channel *prev)
static void openingd_memleak_req_done(struct subd *open_daemon,
const u8 *msg, const int *fds UNUSED,
struct leak_detect *leaks)
{
bool found_leak;
if (!fromwire_openingd_dev_memleak_reply(msg, &found_leak))
fatal("Bad opening_dev_memleak");
if (found_leak)
report_subd_memleak(leaks, open_daemon);
}
void peer_dev_memleak(struct lightningd *ld, struct leak_detect *leaks)
{
struct peer *p;
list_for_each(&cmd->ld->peers, p, list) {
list_for_each(&ld->peers, p, list) {
struct channel *c;
if (p->uncommitted_channel) {
struct subd *openingd = p->uncommitted_channel->open_daemon;
start_leak_request(subd_req(openingd, openingd,
take(towire_openingd_dev_memleak(NULL)),
-1, 0, openingd_memleak_req_done, leaks),
leaks);
}
list_for_each(&p->channels, c, list) {
if (c == prev) {
prev = NULL;
continue;
}
if (!c->owner)
continue;
if (prev != NULL)
continue;
/* Note: closingd and dualopend do their own
* checking automatically */
if (channel_unsaved(c))
continue;
if (streq(c->owner->name, "channeld")) {
subd_req(c, c->owner,
start_leak_request(subd_req(c, c->owner,
take(towire_channeld_dev_memleak(NULL)),
-1, 0, channeld_memleak_req_done, cmd);
tal_add_destructor2(c->owner,
subd_died_forget_memleak,
cmd);
return;
}
if (streq(c->owner->name, "onchaind")) {
subd_req(c, c->owner,
-1, 0, channeld_memleak_req_done, leaks),
leaks);
} else if (streq(c->owner->name, "onchaind")) {
start_leak_request(subd_req(c, c->owner,
take(towire_onchaind_dev_memleak(NULL)),
-1, 0, onchaind_memleak_req_done, cmd);
tal_add_destructor2(c->owner,
subd_died_forget_memleak,
cmd);
return;
-1, 0, onchaind_memleak_req_done, leaks),
leaks);
}
/* FIXME: dualopend doesn't support memleak
* when we ask */
}
}
peer_memleak_done(cmd, NULL);
}
void peer_dev_memleak(struct command *cmd)
{
peer_memleak_req_next(cmd, NULL);
}
#endif /* DEVELOPER */

View File

@ -94,7 +94,8 @@ struct amount_msat channel_amount_receivable(const struct channel *channel);
struct htlc_in_map *load_channels_from_wallet(struct lightningd *ld);
#if DEVELOPER
void peer_dev_memleak(struct command *cmd);
struct leak_detect;
void peer_dev_memleak(struct lightningd *ld, struct leak_detect *leaks);
#endif /* DEVELOPER */
/* Triggered at each new block. */

View File

@ -138,11 +138,11 @@ static void disable_cb(void *disabler UNUSED, struct subd_req *sr)
sr->disabler = NULL;
}
static void add_req(const tal_t *ctx,
struct subd *sd, int type, size_t num_fds_in,
void (*replycb)(struct subd *, const u8 *, const int *,
void *),
void *replycb_data)
static struct subd_req *add_req(const tal_t *ctx,
struct subd *sd, int type, size_t num_fds_in,
void (*replycb)(struct subd *, const u8 *, const int *,
void *),
void *replycb_data)
{
struct subd_req *sr = tal(sd, struct subd_req);
@ -164,6 +164,8 @@ static void add_req(const tal_t *ctx,
/* Keep in FIFO order: we sent in order, so replies will be too. */
list_add_tail(&sd->reqs, &sr->list);
tal_add_destructor(sr, destroy_subd_req);
return sr;
}
/* Caller must free. */
@ -840,12 +842,12 @@ void subd_send_fd(struct subd *sd, int fd)
msg_enqueue_fd(sd->outq, fd);
}
void subd_req_(const tal_t *ctx,
struct subd *sd,
const u8 *msg_out,
int fd_out, size_t num_fds_in,
void (*replycb)(struct subd *, const u8 *, const int *, void *),
void *replycb_data)
struct subd_req *subd_req_(const tal_t *ctx,
struct subd *sd,
const u8 *msg_out,
int fd_out, size_t num_fds_in,
void (*replycb)(struct subd *, const u8 *, const int *, void *),
void *replycb_data)
{
/* Grab type now in case msg_out is taken() */
int type = fromwire_peektype(msg_out);
@ -854,7 +856,7 @@ void subd_req_(const tal_t *ctx,
if (fd_out >= 0)
subd_send_fd(sd, fd_out);
add_req(ctx, sd, type, num_fds_in, replycb, replycb_data);
return add_req(ctx, sd, type, num_fds_in, replycb, replycb_data);
}
/* SIGALRM terminates by default: we just want it to interrupt waitpid(),

View File

@ -190,7 +190,7 @@ void subd_send_fd(struct subd *sd, int fd);
struct subd *, \
const u8 *, const int *), \
(replycb_data))
void subd_req_(const tal_t *ctx,
struct subd_req *subd_req_(const tal_t *ctx,
struct subd *sd,
const u8 *msg_out,
int fd_out, size_t num_fds_in,

View File

@ -222,6 +222,9 @@ void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct n
/* Generated stub for fromwire_onchaind_dev_memleak_reply */
bool fromwire_onchaind_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEEDED)
{ fprintf(stderr, "fromwire_onchaind_dev_memleak_reply called!\n"); abort(); }
/* Generated stub for fromwire_openingd_dev_memleak_reply */
bool fromwire_openingd_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEEDED)
{ fprintf(stderr, "fromwire_openingd_dev_memleak_reply called!\n"); abort(); }
/* Generated stub for get_block_height */
u32 get_block_height(const struct chain_topology *topo UNNEEDED)
{ fprintf(stderr, "get_block_height called!\n"); abort(); }
@ -558,9 +561,6 @@ struct command_result *param_u64(struct command *cmd UNNEEDED, const char *name
/* Generated stub for peer_active_channel */
struct channel *peer_active_channel(struct peer *peer UNNEEDED)
{ fprintf(stderr, "peer_active_channel called!\n"); abort(); }
/* Generated stub for peer_memleak_done */
void peer_memleak_done(struct command *cmd UNNEEDED, struct subd *leaker UNNEEDED)
{ fprintf(stderr, "peer_memleak_done called!\n"); abort(); }
/* Generated stub for peer_normal_channel */
struct channel *peer_normal_channel(struct peer *peer UNNEEDED)
{ fprintf(stderr, "peer_normal_channel called!\n"); abort(); }
@ -594,12 +594,19 @@ bool plugin_hook_call_(struct lightningd *ld UNNEEDED, const struct plugin_hook
void plugin_request_send(struct plugin *plugin UNNEEDED,
struct jsonrpc_request *req TAKES UNNEEDED)
{ fprintf(stderr, "plugin_request_send called!\n"); abort(); }
/* Generated stub for report_subd_memleak */
void report_subd_memleak(struct leak_detect *leak_detect UNNEEDED, struct subd *leaker UNNEEDED)
{ fprintf(stderr, "report_subd_memleak called!\n"); abort(); }
/* Generated stub for resolve_close_command */
void resolve_close_command(struct lightningd *ld UNNEEDED, struct channel *channel UNNEEDED,
bool cooperative UNNEEDED)
{ fprintf(stderr, "resolve_close_command called!\n"); abort(); }
/* Generated stub for start_leak_request */
void start_leak_request(const struct subd_req *req UNNEEDED,
struct leak_detect *leak_detect UNNEEDED)
{ fprintf(stderr, "start_leak_request called!\n"); abort(); }
/* Generated stub for subd_req_ */
void subd_req_(const tal_t *ctx UNNEEDED,
struct subd_req *subd_req_(const tal_t *ctx UNNEEDED,
struct subd *sd UNNEEDED,
const u8 *msg_out UNNEEDED,
int fd_out UNNEEDED, size_t num_fds_in UNNEEDED,
@ -647,6 +654,9 @@ void towire_node_id(u8 **pptr UNNEEDED, const struct node_id *id UNNEEDED)
/* Generated stub for towire_onchaind_dev_memleak */
u8 *towire_onchaind_dev_memleak(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "towire_onchaind_dev_memleak called!\n"); abort(); }
/* Generated stub for towire_openingd_dev_memleak */
u8 *towire_openingd_dev_memleak(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "towire_openingd_dev_memleak called!\n"); abort(); }
/* Generated stub for towire_warningfmt */
u8 *towire_warningfmt(const tal_t *ctx UNNEEDED,
const struct channel_id *channel UNNEEDED,

View File

@ -163,6 +163,9 @@ bool fromwire_hsmd_sign_commitment_tx_reply(const void *p UNNEEDED, struct bitco
/* Generated stub for fromwire_onchaind_dev_memleak_reply */
bool fromwire_onchaind_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEEDED)
{ fprintf(stderr, "fromwire_onchaind_dev_memleak_reply called!\n"); abort(); }
/* Generated stub for fromwire_openingd_dev_memleak_reply */
bool fromwire_openingd_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEEDED)
{ fprintf(stderr, "fromwire_openingd_dev_memleak_reply called!\n"); abort(); }
/* Generated stub for get_block_height */
u32 get_block_height(const struct chain_topology *topo UNNEEDED)
{ fprintf(stderr, "get_block_height called!\n"); abort(); }
@ -609,9 +612,6 @@ void payment_store(struct lightningd *ld UNNEEDED, struct wallet_payment *paymen
void payment_succeeded(struct lightningd *ld UNNEEDED, struct htlc_out *hout UNNEEDED,
const struct preimage *rval UNNEEDED)
{ fprintf(stderr, "payment_succeeded called!\n"); abort(); }
/* Generated stub for peer_memleak_done */
void peer_memleak_done(struct command *cmd UNNEEDED, struct subd *leaker UNNEEDED)
{ fprintf(stderr, "peer_memleak_done called!\n"); abort(); }
/* Generated stub for peer_restart_dualopend */
void peer_restart_dualopend(struct peer *peer UNNEEDED,
struct peer_fd *peer_fd UNNEEDED,
@ -645,6 +645,9 @@ struct route_step *process_onionpacket(
bool has_realm
)
{ fprintf(stderr, "process_onionpacket called!\n"); abort(); }
/* Generated stub for report_subd_memleak */
void report_subd_memleak(struct leak_detect *leak_detect UNNEEDED, struct subd *leaker UNNEEDED)
{ fprintf(stderr, "report_subd_memleak called!\n"); abort(); }
/* Generated stub for resolve_close_command */
void resolve_close_command(struct lightningd *ld UNNEEDED, struct channel *channel UNNEEDED,
bool cooperative UNNEEDED)
@ -654,11 +657,15 @@ u8 *serialize_onionpacket(
const tal_t *ctx UNNEEDED,
const struct onionpacket *packet UNNEEDED)
{ fprintf(stderr, "serialize_onionpacket called!\n"); abort(); }
/* Generated stub for start_leak_request */
void start_leak_request(const struct subd_req *req UNNEEDED,
struct leak_detect *leak_detect UNNEEDED)
{ fprintf(stderr, "start_leak_request called!\n"); abort(); }
/* Generated stub for subd_release_channel */
void subd_release_channel(struct subd *owner UNNEEDED, const void *channel UNNEEDED)
{ fprintf(stderr, "subd_release_channel called!\n"); abort(); }
/* Generated stub for subd_req_ */
void subd_req_(const tal_t *ctx UNNEEDED,
struct subd_req *subd_req_(const tal_t *ctx UNNEEDED,
struct subd *sd UNNEEDED,
const u8 *msg_out UNNEEDED,
int fd_out UNNEEDED, size_t num_fds_in UNNEEDED,
@ -763,6 +770,9 @@ u8 *towire_onchaind_dev_memleak(const tal_t *ctx UNNEEDED)
/* Generated stub for towire_onchaind_known_preimage */
u8 *towire_onchaind_known_preimage(const tal_t *ctx UNNEEDED, const struct preimage *preimage UNNEEDED)
{ fprintf(stderr, "towire_onchaind_known_preimage called!\n"); abort(); }
/* Generated stub for towire_openingd_dev_memleak */
u8 *towire_openingd_dev_memleak(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "towire_openingd_dev_memleak called!\n"); abort(); }
/* Generated stub for towire_permanent_channel_failure */
u8 *towire_permanent_channel_failure(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "towire_permanent_channel_failure called!\n"); abort(); }