Browse Source

openingd: wire up dev_memleak.

This is a bit different from the other cases: we need to iterate through
the peers and ask all the ones in openingd.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
trytravis
Rusty Russell 6 years ago
parent
commit
a42c8bfb38
  1. 7
      lightningd/Makefile
  2. 30
      lightningd/memdump.c
  3. 11
      lightningd/memdump.h
  4. 58
      lightningd/opening_control.c
  5. 6
      lightningd/opening_control.h
  6. 6
      openingd/opening_wire.csv
  7. 25
      openingd/openingd.c

7
lightningd/Makefile

@ -70,6 +70,7 @@ LIGHTNINGD_SRC := \
lightningd/lightningd.c \
lightningd/log.c \
lightningd/log_status.c \
lightningd/memdump.c \
lightningd/onchain_control.c \
lightningd/opening_control.c \
lightningd/options.c \
@ -83,11 +84,7 @@ LIGHTNINGD_SRC := \
lightningd/subd.c \
lightningd/watch.c
# Source files without corresponding headers
LIGHTNINGD_SRC_NOHDR := \
lightningd/memdump.c
LIGHTNINGD_OBJS := $(LIGHTNINGD_SRC:.c=.o) $(LIGHTNINGD_SRC_NOHDR:.c=.o)
LIGHTNINGD_OBJS := $(LIGHTNINGD_SRC:.c=.o)
# Make sure these depend on everything.
ALL_OBJS += $(LIGHTNINGD_OBJS)

30
lightningd/memdump.c

@ -1,5 +1,5 @@
/* Only possible if we're in developer mode. */
#include "config.h"
#include "memdump.h"
#if DEVELOPER
#include <backtrace.h>
#include <ccan/tal/str/str.h>
@ -15,6 +15,7 @@
#include <lightningd/jsonrpc_errors.h>
#include <lightningd/lightningd.h>
#include <lightningd/log.h>
#include <lightningd/opening_control.h>
#include <lightningd/param.h>
#include <lightningd/subd.h>
#include <stdio.h>
@ -254,13 +255,26 @@ static void hsm_dev_memleak_done(struct subd *hsmd,
-1, 0, connect_dev_memleak_done, cmd);
}
void opening_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_hsm_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);
}
}
static void json_memleak(struct command *cmd,
const char *buffer UNNEEDED,
const jsmntok_t *params UNNEEDED)
{
struct lightningd *ld = cmd->ld;
u8 *msg;
if (!param(cmd, buffer, params, NULL))
return;
@ -274,12 +288,8 @@ static void json_memleak(struct command *cmd,
* immediately. */
command_still_pending(cmd);
/* We talk to hsm sync. */
msg = towire_hsm_dev_memleak(NULL);
if (!wire_sync_write(ld->hsm_fd, take(msg)))
fatal("Could not write to HSM: %s", strerror(errno));
hsm_dev_memleak_done(ld->hsm, wire_sync_read(tmpctx, ld->hsm_fd), cmd);
/* This calls opening_memleak_done() async when all done. */
opening_dev_memleak(cmd);
}
static const struct json_command dev_memleak_command = {

11
lightningd/memdump.h

@ -0,0 +1,11 @@
#ifndef LIGHTNING_LIGHTNINGD_MEMDUMP_H
#define LIGHTNING_LIGHTNINGD_MEMDUMP_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <stdbool.h>
struct command;
struct subd;
void opening_memleak_done(struct command *cmd, struct subd *leaker);
#endif /* LIGHTNING_LIGHTNINGD_MEMDUMP_H */

58
lightningd/opening_control.c

@ -675,6 +675,9 @@ static unsigned int openingd_msg(struct subd *openingd,
case WIRE_OPENING_INIT:
case WIRE_OPENING_FUNDER:
case WIRE_OPENING_CAN_ACCEPT_CHANNEL:
case WIRE_OPENING_DEV_MEMLEAK:
/* Replies never get here */
case WIRE_OPENING_DEV_MEMLEAK_REPLY:
break;
}
log_broken(openingd->log, "Unexpected msg %s: %s",
@ -855,3 +858,58 @@ static const struct json_command fund_channel_command = {
"Fund channel with {id} using {satoshi} (or 'all') satoshis, at optional {feerate}"
};
AUTODATA(json_command, &fund_channel_command);
#if DEVELOPER
/* Indented to avoid include ordering check */
#include <lightningd/memdump.h>
/* Mutual recursion */
static void opening_memleak_req_next(struct command *cmd, struct peer *prev);
static void opening_memleak_req_done(struct subd *openingd,
const u8 *msg, const int *fds UNUSED,
struct command *cmd)
{
bool found_leak;
struct uncommitted_channel *uc = openingd->channel;
if (!fromwire_opening_dev_memleak_reply(msg, &found_leak)) {
command_fail(cmd, LIGHTNINGD, "Bad opening_dev_memleak");
return;
}
if (found_leak) {
opening_memleak_done(cmd, openingd);
return;
}
opening_memleak_req_next(cmd, uc->peer);
}
static void opening_memleak_req_next(struct command *cmd, struct peer *prev)
{
struct peer *p;
list_for_each(&cmd->ld->peers, p, list) {
if (!p->uncommitted_channel)
continue;
if (p == prev) {
prev = NULL;
continue;
}
if (prev != NULL)
continue;
/* FIXME: If openingd dies, we'll get stuck here! */
subd_req(p,
p->uncommitted_channel->openingd,
take(towire_opening_dev_memleak(NULL)),
-1, 0, opening_memleak_req_done, cmd);
return;
}
opening_memleak_done(cmd, NULL);
}
void opening_dev_memleak(struct command *cmd)
{
opening_memleak_req_next(cmd, NULL);
}
#endif /* DEVELOPER */

6
lightningd/opening_control.h

@ -22,4 +22,10 @@ void opening_peer_no_active_channels(struct peer *peer);
void kill_uncommitted_channel(struct uncommitted_channel *uc,
const char *why);
#if DEVELOPER
struct command;
/* Calls report_leak_info() async. */
void opening_dev_memleak(struct command *cmd);
#endif
#endif /* LIGHTNING_LIGHTNINGD_OPENING_CONTROL_H */

6
openingd/opening_wire.csv

@ -85,3 +85,9 @@ opening_fundee,,feerate_per_kw,u32
opening_fundee,,msglen,u16
opening_fundee,,funding_signed_msg,msglen*u8
opening_fundee,,our_channel_reserve_satoshis,u64
# master -> openingd: do you have a memleak?
opening_dev_memleak,6033
opening_dev_memleak_reply,6133
opening_dev_memleak_reply,,leak,bool

Can't render this file because it has a wrong number of fields in line 5.

25
openingd/openingd.c

@ -13,6 +13,7 @@
#include <common/gen_peer_status_wire.h>
#include <common/initial_channel.h>
#include <common/key_derive.h>
#include <common/memleak.h>
#include <common/peer_billboard.h>
#include <common/peer_failed.h>
#include <common/pseudorand.h>
@ -1043,6 +1044,24 @@ static void fail_if_all_error(const u8 *inner)
exit(0);
}
#if DEVELOPER
static void handle_dev_memleak(struct state *state, const u8 *msg)
{
struct htable *memtable;
bool found_leak;
memtable = memleak_enter_allocations(tmpctx, msg, msg);
/* Now delete state and things it has pointers to. */
memleak_remove_referenced(memtable, state);
found_leak = dump_memleak(memtable);
wire_sync_write(REQ_FD,
take(towire_opening_dev_memleak_reply(NULL,
found_leak)));
}
#endif /* DEVELOPER */
static u8 *handle_master_in(struct state *state)
{
u8 *msg = wire_sync_read(tmpctx, REQ_FD);
@ -1076,6 +1095,12 @@ static u8 *handle_master_in(struct state *state)
state->can_accept_channel = true;
return NULL;
case WIRE_OPENING_DEV_MEMLEAK:
#if DEVELOPER
handle_dev_memleak(state, msg);
return NULL;
#endif
case WIRE_OPENING_DEV_MEMLEAK_REPLY:
case WIRE_OPENING_INIT:
case WIRE_OPENING_FUNDER_REPLY:
case WIRE_OPENING_FUNDEE:

Loading…
Cancel
Save