Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions connectd/connectd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2014,6 +2014,10 @@ static void dev_connect_memleak(struct daemon *daemon, const u8 *msg)
struct htable *memtable;
bool found_leak;

/* As a side-effect, this tells us lightningd will be unresponsive,
* so don't complain (and break CI!) if it's slow. */
daemon->dev_lightningd_is_slow = true;

memtable = memleak_start(tmpctx);
memleak_ptr(memtable, msg);

Expand Down Expand Up @@ -2465,6 +2469,7 @@ int main(int argc, char *argv[])
daemon->dev_suppress_gossip = false;
daemon->custom_msgs = NULL;
daemon->dev_exhausted_fds = false;
daemon->dev_lightningd_is_slow = false;
/* We generally allow 1MB per second per peer, except for dev testing */
daemon->gossip_stream_limit = 1000000;
daemon->scid_htable = new_htable(daemon, scid_htable);
Expand Down
2 changes: 2 additions & 0 deletions connectd/connectd.h
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,8 @@ struct daemon {
bool dev_no_reconnect;
/* --dev-fast-reconnect */
bool dev_fast_reconnect;
/* Don't complain about lightningd being unresponsive. */
bool dev_lightningd_is_slow;
};

/* Called by io_tor_connect once it has a connection out. */
Expand Down
2 changes: 1 addition & 1 deletion connectd/multiplex.c
Original file line number Diff line number Diff line change
Expand Up @@ -1150,7 +1150,7 @@ static struct io_plan *write_to_subd(struct io_conn *subd_conn,
if (subd->peer->peer_in_lastmsg != -1) {
u64 msec = time_to_msec(timemono_between(time_mono(),
subd->peer->peer_in_lasttime));
if (msec > 5000)
if (msec > 5000 && !subd->peer->daemon->dev_lightningd_is_slow)
status_peer_broken(&subd->peer->id,
"wake delay for %s: %"PRIu64"msec",
peer_wire_name(subd->peer->peer_in_lastmsg),
Expand Down
2 changes: 2 additions & 0 deletions lightningd/channel_gossip.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ static struct state_transition allowed_transitions[] = {
"Unannounced channel closed onchain." },
{ CGOSSIP_CHANNEL_UNANNOUNCED_DYING, CGOSSIP_CHANNEL_ANNOUNCED_DYING,
"Unannounced closing channel reached announce depth." },
{ CGOSSIP_CHANNEL_UNANNOUNCED_DYING, CGOSSIP_CHANNEL_ANNOUNCED_DEAD,
"Unannounced closing channel reached announce depth and was closed in same block." },
{ CGOSSIP_WAITING_FOR_ANNOUNCE_DEPTH, CGOSSIP_ANNOUNCED,
"Channel fully announced" },
{ CGOSSIP_WAITING_FOR_MATCHING_PEER_SIGS, CGOSSIP_ANNOUNCED,
Expand Down
71 changes: 37 additions & 34 deletions lightningd/memdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ static const struct json_command dev_memdump_command = {
};
AUTODATA(json_command, &dev_memdump_command);


static void memleak_log(struct logger *log, const char *fmt, ...)
{
va_list ap;
Expand All @@ -91,16 +92,48 @@ static void memleak_log(struct logger *log, const char *fmt, ...)
va_end(ap);
}

static void finish_report(const struct leak_detect *leaks)
static bool lightningd_check_leaks(struct command *cmd)
{
struct lightningd *ld = cmd->ld;
struct htable *memtable;

/* Enter everything, except this cmd and its jcon */
memtable = memleak_start(cmd);

/* This command is not a leak! */
memleak_ptr(memtable, cmd);
memleak_ignore_children(memtable, cmd);

/* Now delete ld and those which it has pointers to. */
memleak_scan_obj(memtable, ld);

return dump_memleak(memtable, memleak_log, ld->log);
}

static void finish_report(struct leak_detect *leaks)
{
bool found_leak;
struct json_stream *response;
const u8 *msg;

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

/* Check for our own leaks. */
if (lightningd_check_leaks(leaks->cmd))
tal_arr_expand(&leaks->leakers, "lightningd");

/* Check hsmd for leaks. */
msg = hsm_sync_req(tmpctx, leaks->cmd->ld, take(towire_hsmd_dev_memleak(NULL)));
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, leaks->cmd->ld->hsm);

response = json_stream_success(leaks->cmd);
json_array_start(response, "leaks");
for (size_t num_leakers = 0;
Expand Down Expand Up @@ -177,32 +210,12 @@ static void connect_dev_memleak_done(struct subd *connectd,
report_subd_memleak(leaks, connectd);
}

static bool lightningd_check_leaks(struct command *cmd)
{
struct lightningd *ld = cmd->ld;
struct htable *memtable;

/* Enter everything, except this cmd and its jcon */
memtable = memleak_start(cmd);

/* This command is not a leak! */
memleak_ptr(memtable, cmd);
memleak_ignore_children(memtable, cmd);

/* Now delete ld and those which it has pointers to. */
memleak_scan_obj(memtable, ld);

return dump_memleak(memtable, memleak_log, ld->log);
}

static struct command_result *json_memleak(struct command *cmd,
const char *buffer,
const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params)
{
struct lightningd *ld = cmd->ld;
const u8 *msg;
bool found_leak;
struct leak_detect *leaks;

if (!param_check(cmd, buffer, params, NULL))
Expand All @@ -221,19 +234,9 @@ static struct command_result *json_memleak(struct command *cmd,
leaks->num_outstanding_requests = 0;
leaks->leakers = tal_arr(leaks, const char *, 0);

/* Check for our own leaks. */
if (lightningd_check_leaks(cmd))
tal_arr_expand(&leaks->leakers, "lightningd");

/* hsmd is sync, so do that first. */
msg = hsm_sync_req(tmpctx, cmd->ld, take(towire_hsmd_dev_memleak(NULL)));
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. */
/* Now do all the async ones. By doing connectd first, it
* has the side-effect of suppressing the complaint it makes
* about us being unresponsive. */
start_leak_request(subd_req(ld->connectd, ld->connectd,
take(towire_connectd_dev_memleak(NULL)),
-1, 0, connect_dev_memleak_done, leaks),
Expand Down
6 changes: 4 additions & 2 deletions tests/test_coinmoves.py
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,8 @@ def test_coinmoves_unilateral_htlc_timeout(node_factory, bitcoind):

line = l1.daemon.wait_for_log('Resolved OUR_UNILATERAL/OUR_HTLC by our proposal OUR_HTLC_TIMEOUT_TX')
htlc_timeout_txid = re.search(r'by our proposal OUR_HTLC_TIMEOUT_TX \(([0-9a-f]{64})\)', line).group(1)
# Usually 6358000, but if we're lucky it's 6366000.
htlc_timeout_change_msats = bitcoind.rpc.gettxout(htlc_timeout_txid, 1)['value'] * 100_000_000_000
expected_chain1 += [{'account_id': 'wallet',
'blockheight': 115,
'credit_msat': 0,
Expand All @@ -906,10 +908,10 @@ def test_coinmoves_unilateral_htlc_timeout(node_factory, bitcoind):
# Change
{'account_id': 'wallet',
'blockheight': 115,
'credit_msat': (15579000 + 6358000) - anchor_change_msats,
'credit_msat': htlc_timeout_change_msats,
'debit_msat': 0,
'extra_tags': [],
'output_msat': (15579000 + 6358000) - anchor_change_msats,
'output_msat': htlc_timeout_change_msats,
'primary_tag': 'deposit',
'utxo': f"{htlc_timeout_txid}:1"},
{'account_id': fundchannel['channel_id'],
Expand Down
5 changes: 4 additions & 1 deletion tests/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -4719,8 +4719,11 @@ def test_injectonionmessage(node_factory):

def test_connect_ratelimit(node_factory, bitcoind):
"""l1 has 5 peers, restarts, make sure we limit"""
# Sending nodes SIGSTOP at the wrong time makes connectd complain about
# how long operations took!
nodes = node_factory.get_nodes(6,
opts=[{'dev-limit-connections-inflight': None, 'may_reconnect': True}] + [{'may_reconnect': True}] * 5)
opts=[{'dev-limit-connections-inflight': None, 'may_reconnect': True}]
+ [{'may_reconnect': True, 'broken_log': "connectd: wake delay for"}] * 5)

l1 = nodes[0]
nodes = nodes[1:]
Expand Down
Loading