mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 14:42:40 +01:00
dualopend: restore memleak calls.
And implement a timeout (20 seconds) just in case it's not listening. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
84e0e743eb
commit
d7ffb712e5
7 changed files with 85 additions and 14 deletions
|
@ -3026,6 +3026,8 @@ static unsigned int dual_opend_msg(struct subd *dualopend,
|
||||||
case WIRE_DUALOPEND_SEND_TX_SIGS:
|
case WIRE_DUALOPEND_SEND_TX_SIGS:
|
||||||
case WIRE_DUALOPEND_SEND_SHUTDOWN:
|
case WIRE_DUALOPEND_SEND_SHUTDOWN:
|
||||||
case WIRE_DUALOPEND_DEPTH_REACHED:
|
case WIRE_DUALOPEND_DEPTH_REACHED:
|
||||||
|
case WIRE_DUALOPEND_DEV_MEMLEAK:
|
||||||
|
case WIRE_DUALOPEND_DEV_MEMLEAK_REPLY:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,9 +129,19 @@ static void finish_report(const struct leak_detect *leaks)
|
||||||
struct htable *memtable;
|
struct htable *memtable;
|
||||||
const tal_t *i;
|
const tal_t *i;
|
||||||
const uintptr_t *backtrace;
|
const uintptr_t *backtrace;
|
||||||
struct command *cmd = leaks->cmd;
|
struct command *cmd;
|
||||||
struct lightningd *ld = cmd->ld;
|
struct lightningd *ld;
|
||||||
struct json_stream *response = json_stream_success(cmd);
|
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 */
|
/* Enter everything, except this cmd and its jcon */
|
||||||
memtable = memleak_find_allocations(cmd, cmd, cmd->jcon);
|
memtable = memleak_find_allocations(cmd, cmd, cmd->jcon);
|
||||||
|
@ -146,6 +156,7 @@ static void finish_report(const struct leak_detect *leaks)
|
||||||
/* Now delete ld and those which it has pointers to. */
|
/* Now delete ld and those which it has pointers to. */
|
||||||
memleak_remove_region(memtable, ld, sizeof(*ld));
|
memleak_remove_region(memtable, ld, sizeof(*ld));
|
||||||
|
|
||||||
|
response = json_stream_success(cmd);
|
||||||
json_array_start(response, "leaks");
|
json_array_start(response, "leaks");
|
||||||
while ((i = memleak_get(memtable, &backtrace)) != NULL) {
|
while ((i = memleak_get(memtable, &backtrace)) != NULL) {
|
||||||
const tal_t *p;
|
const tal_t *p;
|
||||||
|
@ -176,6 +187,12 @@ static void finish_report(const struct leak_detect *leaks)
|
||||||
was_pending(command_success(cmd, response));
|
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,
|
static void leak_detect_req_done(const struct subd_req *req,
|
||||||
struct leak_detect *leak_detect)
|
struct leak_detect *leak_detect)
|
||||||
{
|
{
|
||||||
|
@ -274,6 +291,10 @@ static struct command_result *json_memleak(struct command *cmd,
|
||||||
|
|
||||||
/* Ask all per-peer daemons */
|
/* Ask all per-peer daemons */
|
||||||
peer_dev_memleak(ld, leaks);
|
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);
|
return command_still_pending(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
#include <lightningd/subd.h>
|
#include <lightningd/subd.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <onchaind/onchaind_wiregen.h>
|
#include <onchaind/onchaind_wiregen.h>
|
||||||
|
#include <openingd/dualopend_wiregen.h>
|
||||||
#include <openingd/openingd_wiregen.h>
|
#include <openingd/openingd_wiregen.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -2363,6 +2364,19 @@ static void openingd_memleak_req_done(struct subd *open_daemon,
|
||||||
report_subd_memleak(leaks, 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)
|
void peer_dev_memleak(struct lightningd *ld, struct leak_detect *leaks)
|
||||||
{
|
{
|
||||||
struct peer *p;
|
struct peer *p;
|
||||||
|
@ -2390,9 +2404,12 @@ void peer_dev_memleak(struct lightningd *ld, struct leak_detect *leaks)
|
||||||
take(towire_onchaind_dev_memleak(NULL)),
|
take(towire_onchaind_dev_memleak(NULL)),
|
||||||
-1, 0, onchaind_memleak_req_done, leaks),
|
-1, 0, onchaind_memleak_req_done, leaks),
|
||||||
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 */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,6 +207,9 @@ bool fromwire_channeld_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNE
|
||||||
/* Generated stub for fromwire_connectd_peer_connected */
|
/* 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)
|
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(); }
|
{ 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 */
|
/* Generated stub for fromwire_hsmd_sign_bolt12_reply */
|
||||||
bool fromwire_hsmd_sign_bolt12_reply(const void *p UNNEEDED, struct bip340sig *sig UNNEEDED)
|
bool fromwire_hsmd_sign_bolt12_reply(const void *p UNNEEDED, struct bip340sig *sig UNNEEDED)
|
||||||
{ fprintf(stderr, "fromwire_hsmd_sign_bolt12_reply called!\n"); abort(); }
|
{ fprintf(stderr, "fromwire_hsmd_sign_bolt12_reply called!\n"); abort(); }
|
||||||
|
@ -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 */
|
/* 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)
|
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(); }
|
{ 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 */
|
/* Generated stub for towire_errorfmt */
|
||||||
u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
|
u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
|
||||||
const struct channel_id *channel UNNEEDED,
|
const struct channel_id *channel UNNEEDED,
|
||||||
|
|
|
@ -881,18 +881,23 @@ static bool is_segwit_output(struct wally_tx_output *output,
|
||||||
* at closing time, rather than when it askes.
|
* at closing time, rather than when it askes.
|
||||||
*/
|
*/
|
||||||
#if DEVELOPER
|
#if DEVELOPER
|
||||||
static void dualopend_dev_memleak(struct state *state)
|
static void handle_dev_memleak(struct state *state, const u8 *msg)
|
||||||
{
|
{
|
||||||
struct htable *memtable;
|
struct htable *memtable;
|
||||||
|
bool found_leak;
|
||||||
|
|
||||||
/* Populate a hash table with all our allocations. */
|
/* Populate a hash table with all our allocations (except msg, which
|
||||||
memtable = memleak_find_allocations(tmpctx, NULL, NULL);
|
* is in use right now). */
|
||||||
|
memtable = memleak_find_allocations(tmpctx, msg, msg);
|
||||||
|
|
||||||
/* Now delete state and things it has pointers to. */
|
/* Now delete state and things it has pointers to. */
|
||||||
memleak_remove_region(memtable, state, tal_bytelen(state));
|
memleak_remove_region(memtable, state, tal_bytelen(state));
|
||||||
|
|
||||||
/* If there's anything left, dump it to logs, and return true. */
|
/* 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 */
|
#endif /* DEVELOPER */
|
||||||
|
|
||||||
|
@ -1053,7 +1058,14 @@ fetch_psbt_changes(struct state *state,
|
||||||
psbt);
|
psbt);
|
||||||
|
|
||||||
wire_sync_write(REQ_FD, take(msg));
|
wire_sync_write(REQ_FD, take(msg));
|
||||||
|
|
||||||
msg = wire_sync_read(tmpctx, REQ_FD);
|
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)) {
|
if (fromwire_dualopend_fail(msg, msg, &err)) {
|
||||||
open_err_warn(state, "%s", err);
|
open_err_warn(state, "%s", err);
|
||||||
|
@ -3601,6 +3613,11 @@ static u8 *handle_master_in(struct state *state)
|
||||||
enum dualopend_wire t = fromwire_peektype(msg);
|
enum dualopend_wire t = fromwire_peektype(msg);
|
||||||
|
|
||||||
switch (t) {
|
switch (t) {
|
||||||
|
case WIRE_DUALOPEND_DEV_MEMLEAK:
|
||||||
|
#if DEVELOPER
|
||||||
|
handle_dev_memleak(state, msg);
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
case WIRE_DUALOPEND_OPENER_INIT:
|
case WIRE_DUALOPEND_OPENER_INIT:
|
||||||
opener_start(state, msg);
|
opener_start(state, msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -3627,6 +3644,7 @@ static u8 *handle_master_in(struct state *state)
|
||||||
case WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY:
|
case WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY:
|
||||||
case WIRE_DUALOPEND_RBF_VALID:
|
case WIRE_DUALOPEND_RBF_VALID:
|
||||||
case WIRE_DUALOPEND_VALIDATE_LEASE_REPLY:
|
case WIRE_DUALOPEND_VALIDATE_LEASE_REPLY:
|
||||||
|
case WIRE_DUALOPEND_DEV_MEMLEAK_REPLY:
|
||||||
|
|
||||||
/* Messages we send */
|
/* Messages we send */
|
||||||
case WIRE_DUALOPEND_GOT_OFFER:
|
case WIRE_DUALOPEND_GOT_OFFER:
|
||||||
|
@ -3949,11 +3967,6 @@ int main(int argc, char *argv[])
|
||||||
dualopend_wire_name(fromwire_peektype(msg)));
|
dualopend_wire_name(fromwire_peektype(msg)));
|
||||||
tal_free(msg);
|
tal_free(msg);
|
||||||
|
|
||||||
#if DEVELOPER
|
|
||||||
/* Now look for memory leaks. */
|
|
||||||
dualopend_dev_memleak(state);
|
|
||||||
#endif /* DEVELOPER */
|
|
||||||
|
|
||||||
/* This frees the entire tal tree. */
|
/* This frees the entire tal tree. */
|
||||||
tal_free(state);
|
tal_free(state);
|
||||||
daemon_shutdown();
|
daemon_shutdown();
|
||||||
|
|
|
@ -220,6 +220,12 @@ msgtype,dualopend_fail_fallen_behind,1028
|
||||||
# Shutdown is complete, ready for closing negotiation. + peer_fd & gossip_fd.
|
# Shutdown is complete, ready for closing negotiation. + peer_fd & gossip_fd.
|
||||||
msgtype,dualopend_shutdown_complete,7025
|
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
|
# dualopend -> master: this was a dry run, here's some info about this open
|
||||||
msgtype,dualopend_dry_run,7026
|
msgtype,dualopend_dry_run,7026
|
||||||
msgdata,dualopend_dry_run,channel_id,channel_id,
|
msgdata,dualopend_dry_run,channel_id,channel_id,
|
||||||
|
|
Can't render this file because it has a wrong number of fields in line 14.
|
|
@ -151,6 +151,9 @@ bool fromwire_channeld_sending_commitsig(const tal_t *ctx UNNEEDED, const void *
|
||||||
/* Generated stub for fromwire_connectd_peer_connected */
|
/* 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)
|
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(); }
|
{ 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 */
|
/* 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)
|
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(); }
|
{ fprintf(stderr, "fromwire_hsmd_get_output_scriptpubkey_reply called!\n"); abort(); }
|
||||||
|
@ -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 */
|
/* 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)
|
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(); }
|
{ 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 */
|
/* Generated stub for towire_errorfmt */
|
||||||
u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
|
u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
|
||||||
const struct channel_id *channel UNNEEDED,
|
const struct channel_id *channel UNNEEDED,
|
||||||
|
|
Loading…
Add table
Reference in a new issue