Skip to content

Commit

Permalink
dualopend: restore memleak calls.
Browse files Browse the repository at this point in the history
And implement a timeout (20 seconds) just in case it's not listening.

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Mar 9, 2022
1 parent 84e0e74 commit d7ffb71
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 14 deletions.
2 changes: 2 additions & 0 deletions lightningd/dual_open_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -3026,6 +3026,8 @@ static unsigned int dual_opend_msg(struct subd *dualopend,
case WIRE_DUALOPEND_SEND_TX_SIGS:
case WIRE_DUALOPEND_SEND_SHUTDOWN:
case WIRE_DUALOPEND_DEPTH_REACHED:
case WIRE_DUALOPEND_DEV_MEMLEAK:
case WIRE_DUALOPEND_DEV_MEMLEAK_REPLY:
break;
}

Expand Down
27 changes: 24 additions & 3 deletions lightningd/memdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,19 @@ 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);
struct command *cmd;
struct lightningd *ld;
struct json_stream *response;

/* If it timed out, we free ourselved and exit! */
if (!leaks->cmd) {
tal_free(leaks);
return;
}

/* Convenience variables */
cmd = leaks->cmd;
ld = cmd->ld;

/* Enter everything, except this cmd and its jcon */
memtable = memleak_find_allocations(cmd, cmd, cmd->jcon);
Expand All @@ -146,6 +156,7 @@ static void finish_report(const struct leak_detect *leaks)
/* Now delete ld and those which it has pointers to. */
memleak_remove_region(memtable, ld, sizeof(*ld));

response = json_stream_success(cmd);
json_array_start(response, "leaks");
while ((i = memleak_get(memtable, &backtrace)) != NULL) {
const tal_t *p;
Expand Down Expand Up @@ -176,6 +187,12 @@ static void finish_report(const struct leak_detect *leaks)
was_pending(command_success(cmd, response));
}

static void leak_detect_timeout(struct leak_detect *leak_detect)
{
finish_report(leak_detect);
leak_detect->cmd = NULL;
}

static void leak_detect_req_done(const struct subd_req *req,
struct leak_detect *leak_detect)
{
Expand Down Expand Up @@ -274,6 +291,10 @@ static struct command_result *json_memleak(struct command *cmd,

/* Ask all per-peer daemons */
peer_dev_memleak(ld, leaks);

/* Set timer: dualopend doesn't always listen! */
notleak(new_reltimer(ld->timers, leaks, time_from_sec(20),
leak_detect_timeout, leaks));
return command_still_pending(cmd);
}

Expand Down
21 changes: 19 additions & 2 deletions lightningd/peer_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#include <lightningd/subd.h>
#include <limits.h>
#include <onchaind/onchaind_wiregen.h>
#include <openingd/dualopend_wiregen.h>
#include <openingd/openingd_wiregen.h>
#include <stdlib.h>
#include <unistd.h>
Expand Down Expand Up @@ -2363,6 +2364,19 @@ static void openingd_memleak_req_done(struct subd *open_daemon,
report_subd_memleak(leaks, open_daemon);
}

static void dualopend_memleak_req_done(struct subd *dualopend,
const u8 *msg, const int *fds UNUSED,
struct leak_detect *leaks)
{
bool found_leak;

if (!fromwire_dualopend_dev_memleak_reply(msg, &found_leak))
fatal("Bad dualopend_dev_memleak");

if (found_leak)
report_subd_memleak(leaks, dualopend);
}

void peer_dev_memleak(struct lightningd *ld, struct leak_detect *leaks)
{
struct peer *p;
Expand Down Expand Up @@ -2390,9 +2404,12 @@ void peer_dev_memleak(struct lightningd *ld, struct leak_detect *leaks)
take(towire_onchaind_dev_memleak(NULL)),
-1, 0, onchaind_memleak_req_done, leaks),
leaks);
} else if (streq(c->owner->name, "dualopend")) {
start_leak_request(subd_req(c, c->owner,
take(towire_dualopend_dev_memleak(NULL)),
-1, 0, dualopend_memleak_req_done, leaks),
leaks);
}
/* FIXME: dualopend doesn't support memleak
* when we ask */
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions lightningd/test/run-invoice-select-inchan.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ bool fromwire_channeld_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNE
/* Generated stub for fromwire_connectd_peer_connected */
bool fromwire_connectd_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id *id UNNEEDED, struct wireaddr_internal *addr UNNEEDED, struct wireaddr **remote_addr UNNEEDED, bool *incoming UNNEEDED, u8 **features UNNEEDED)
{ fprintf(stderr, "fromwire_connectd_peer_connected called!\n"); abort(); }
/* Generated stub for fromwire_dualopend_dev_memleak_reply */
bool fromwire_dualopend_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEEDED)
{ fprintf(stderr, "fromwire_dualopend_dev_memleak_reply called!\n"); abort(); }
/* Generated stub for fromwire_hsmd_sign_bolt12_reply */
bool fromwire_hsmd_sign_bolt12_reply(const void *p UNNEEDED, struct bip340sig *sig UNNEEDED)
{ fprintf(stderr, "fromwire_hsmd_sign_bolt12_reply called!\n"); abort(); }
Expand Down Expand Up @@ -634,6 +637,9 @@ u8 *towire_channeld_specific_feerates(const tal_t *ctx UNNEEDED, u32 feerate_bas
/* Generated stub for towire_connectd_peer_final_msg */
u8 *towire_connectd_peer_final_msg(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED, const u8 *msg UNNEEDED)
{ fprintf(stderr, "towire_connectd_peer_final_msg called!\n"); abort(); }
/* Generated stub for towire_dualopend_dev_memleak */
u8 *towire_dualopend_dev_memleak(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "towire_dualopend_dev_memleak called!\n"); abort(); }
/* Generated stub for towire_errorfmt */
u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
const struct channel_id *channel UNNEEDED,
Expand Down
31 changes: 22 additions & 9 deletions openingd/dualopend.c
Original file line number Diff line number Diff line change
Expand Up @@ -881,18 +881,23 @@ static bool is_segwit_output(struct wally_tx_output *output,
* at closing time, rather than when it askes.
*/
#if DEVELOPER
static void dualopend_dev_memleak(struct state *state)
static void handle_dev_memleak(struct state *state, const u8 *msg)
{
struct htable *memtable;
bool found_leak;

/* Populate a hash table with all our allocations. */
memtable = memleak_find_allocations(tmpctx, NULL, NULL);
/* Populate a hash table with all our allocations (except msg, which
* is in use right now). */
memtable = memleak_find_allocations(tmpctx, msg, msg);

/* Now delete state and things it has pointers to. */
memleak_remove_region(memtable, state, tal_bytelen(state));

/* If there's anything left, dump it to logs, and return true. */
dump_memleak(memtable, memleak_status_broken);
found_leak = dump_memleak(memtable, memleak_status_broken);
wire_sync_write(REQ_FD,
take(towire_dualopend_dev_memleak_reply(NULL,
found_leak)));
}
#endif /* DEVELOPER */

Expand Down Expand Up @@ -1053,7 +1058,14 @@ fetch_psbt_changes(struct state *state,
psbt);

wire_sync_write(REQ_FD, take(msg));

msg = wire_sync_read(tmpctx, REQ_FD);
#if DEVELOPER
while (fromwire_dualopend_dev_memleak(msg)) {
handle_dev_memleak(state, msg);
msg = wire_sync_read(tmpctx, REQ_FD);
}
#endif

if (fromwire_dualopend_fail(msg, msg, &err)) {
open_err_warn(state, "%s", err);
Expand Down Expand Up @@ -3601,6 +3613,11 @@ static u8 *handle_master_in(struct state *state)
enum dualopend_wire t = fromwire_peektype(msg);

switch (t) {
case WIRE_DUALOPEND_DEV_MEMLEAK:
#if DEVELOPER
handle_dev_memleak(state, msg);
#endif
return NULL;
case WIRE_DUALOPEND_OPENER_INIT:
opener_start(state, msg);
return NULL;
Expand All @@ -3627,6 +3644,7 @@ static u8 *handle_master_in(struct state *state)
case WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY:
case WIRE_DUALOPEND_RBF_VALID:
case WIRE_DUALOPEND_VALIDATE_LEASE_REPLY:
case WIRE_DUALOPEND_DEV_MEMLEAK_REPLY:

/* Messages we send */
case WIRE_DUALOPEND_GOT_OFFER:
Expand Down Expand Up @@ -3949,11 +3967,6 @@ int main(int argc, char *argv[])
dualopend_wire_name(fromwire_peektype(msg)));
tal_free(msg);

#if DEVELOPER
/* Now look for memory leaks. */
dualopend_dev_memleak(state);
#endif /* DEVELOPER */

/* This frees the entire tal tree. */
tal_free(state);
daemon_shutdown();
Expand Down
6 changes: 6 additions & 0 deletions openingd/dualopend_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,12 @@ msgtype,dualopend_fail_fallen_behind,1028
# Shutdown is complete, ready for closing negotiation. + peer_fd & gossip_fd.
msgtype,dualopend_shutdown_complete,7025

# master -> dualopend: do you have a memleak?
msgtype,dualopend_dev_memleak,7033

msgtype,dualopend_dev_memleak_reply,7133
msgdata,dualopend_dev_memleak_reply,leak,bool,

# dualopend -> master: this was a dry run, here's some info about this open
msgtype,dualopend_dry_run,7026
msgdata,dualopend_dry_run,channel_id,channel_id,
Expand Down
6 changes: 6 additions & 0 deletions wallet/test/run-wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ bool fromwire_channeld_sending_commitsig(const tal_t *ctx UNNEEDED, const void *
/* Generated stub for fromwire_connectd_peer_connected */
bool fromwire_connectd_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id *id UNNEEDED, struct wireaddr_internal *addr UNNEEDED, struct wireaddr **remote_addr UNNEEDED, bool *incoming UNNEEDED, u8 **features UNNEEDED)
{ fprintf(stderr, "fromwire_connectd_peer_connected called!\n"); abort(); }
/* Generated stub for fromwire_dualopend_dev_memleak_reply */
bool fromwire_dualopend_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEEDED)
{ fprintf(stderr, "fromwire_dualopend_dev_memleak_reply called!\n"); abort(); }
/* Generated stub for fromwire_hsmd_get_output_scriptpubkey_reply */
bool fromwire_hsmd_get_output_scriptpubkey_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **script UNNEEDED)
{ fprintf(stderr, "fromwire_hsmd_get_output_scriptpubkey_reply called!\n"); abort(); }
Expand Down Expand Up @@ -723,6 +726,9 @@ u8 *towire_connectd_peer_disconnected(const tal_t *ctx UNNEEDED, const struct no
/* Generated stub for towire_connectd_peer_final_msg */
u8 *towire_connectd_peer_final_msg(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED, const u8 *msg UNNEEDED)
{ fprintf(stderr, "towire_connectd_peer_final_msg called!\n"); abort(); }
/* Generated stub for towire_dualopend_dev_memleak */
u8 *towire_dualopend_dev_memleak(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "towire_dualopend_dev_memleak called!\n"); abort(); }
/* Generated stub for towire_errorfmt */
u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
const struct channel_id *channel UNNEEDED,
Expand Down

0 comments on commit d7ffb71

Please sign in to comment.