From 20d7ddcb6ed01d81c10add548c0c5847e9dc12da Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 6 Dec 2017 10:04:27 +1030 Subject: [PATCH] json_fund_channel: give more details than "peer died". Rather than using the destructor, hook up the cmd so we can close it. peers are allocated off ld, so they are only destroyed explicitly. Signed-off-by: Rusty Russell --- lightningd/peer_control.c | 50 ++++++++++++++++++++++----------------- lightningd/peer_control.h | 3 +++ 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 26b88068e..06bb0310d 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -175,6 +175,16 @@ static void drop_to_chain(struct peer *peer) broadcast_tx(peer->ld->topology, peer, peer->last_tx, NULL); } +/* This lets us give a more detailed error than just a destructor. */ +static void free_peer(struct peer *peer, const char *msg) +{ + if (peer->opening_cmd) { + command_fail(peer->opening_cmd, "%s", msg); + peer->opening_cmd = NULL; + } + tal_free(peer); +} + void peer_fail_permanent(struct peer *peer, const u8 *msg TAKES) { /* BOLT #1: @@ -183,10 +193,10 @@ void peer_fail_permanent(struct peer *peer, const u8 *msg TAKES) * zero (ie. all bytes zero), in which case it refers to all * channels. */ static const struct channel_id all_channels; + const char *why = tal_strndup(NULL, (char *)msg, tal_len(msg)); - log_unusual(peer->log, "Peer permanent failure in %s: %.*s", - peer_state_name(peer->state), - (int)tal_len(msg), (char *)msg); + log_unusual(peer->log, "Peer permanent failure in %s: %s", + peer_state_name(peer->state), why); /* We can have multiple errors, eg. onchaind failures. */ if (!peer->error) @@ -199,7 +209,8 @@ void peer_fail_permanent(struct peer *peer, const u8 *msg TAKES) if (peer_persists(peer)) drop_to_chain(peer); else - tal_free(peer); + free_peer(peer, why); + tal_free(why); return; } @@ -228,12 +239,13 @@ void peer_internal_error(struct peer *peer, const char *fmt, ...) void peer_fail_transient(struct peer *peer, const char *fmt, ...) { va_list ap; + const char *why; va_start(ap, fmt); - log_info(peer->log, "Peer transient failure in %s: ", - peer_state_name(peer->state)); - logv_add(peer->log, fmt, ap); + why = tal_vfmt(peer, fmt, ap); va_end(ap); + log_info(peer->log, "Peer transient failure in %s: %s", + peer_state_name(peer->state), why); #if DEVELOPER if (dev_disconnect_permanent(peer->ld)) { @@ -248,9 +260,10 @@ void peer_fail_transient(struct peer *peer, const char *fmt, ...) if (!peer_persists(peer)) { log_info(peer->log, "Only reached state %s: forgetting", peer_state_name(peer->state)); - tal_free(peer); + free_peer(peer, why); return; } + tal_free(why); /* Reconnect unless we've dropped/are dropping to chain. */ if (!peer_on_chain(peer) && peer->state != CLOSINGD_COMPLETE) { @@ -350,6 +363,7 @@ static struct peer *new_peer(struct lightningd *ld, peer->seed = NULL; peer->our_msatoshi = NULL; peer->state = UNINITIALIZED; + peer->opening_cmd = NULL; peer->channel_info = NULL; peer->last_tx = NULL; peer->last_sig = NULL; @@ -581,7 +595,8 @@ void peer_connected(struct lightningd *ld, const u8 *msg, /* Reconnect: discard old one. */ case OPENINGD: - tal_free(peer); + free_peer(peer, "peer reconnected"); + peer = NULL; goto return_to_gossipd; case ONCHAIND_CHEATED: @@ -981,12 +996,6 @@ struct funding_channel { struct bitcoin_tx *funding_tx; }; -static void fail_fundchannel_command(struct funding_channel *fc) -{ - /* FIXME: More details? */ - command_fail(fc->cmd, "Peer died"); -} - static void funding_broadcast_failed(struct peer *peer, int exitstatus, const char *err) { @@ -1250,7 +1259,7 @@ static void handle_irrevocably_resolved(struct peer *peer, const u8 *msg) log_info(peer->log, "onchaind complete, forgetting peer"); /* This will also free onchaind. */ - tal_free(peer); + free_peer(peer, "onchaind complete, forgetting peer"); } static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds) @@ -1562,15 +1571,12 @@ static void opening_got_hsm_funding_sig(struct funding_channel *fc, fc->peer->funding_txid, fc->peer->funding_outnum, funding_spent, NULL); - /* We could defer until after funding locked, but makes testing - * harder. */ - tal_del_destructor(fc, fail_fundchannel_command); - json_object_start(response, NULL); linear = linearize_tx(response, tx); json_add_hex(response, "tx", linear, tal_len(linear)); json_object_end(response); - command_success(fc->cmd, response); + command_success(fc->peer->opening_cmd, response); + fc->peer->opening_cmd = NULL; /* Start normal channel daemon. */ peer_start_channeld(fc->peer, cs, peer_fd, gossip_fd, NULL, false); @@ -2522,7 +2528,7 @@ static void peer_offer_channel(struct lightningd *ld, /* Peer now owns fc; if it dies, we fail fc. */ tal_steal(fc->peer, fc); - tal_add_destructor(fc, fail_fundchannel_command); + fc->peer->opening_cmd = fc->cmd; subd_req(fc, fc->peer->owner, take(msg), -1, 2, opening_funder_finished, fc); diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 53c7c8c6d..335a1022d 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -41,6 +41,9 @@ struct peer { /* Which side offered channel? */ enum side funder; + /* Command which ordered us to open channel, if any. */ + struct command *opening_cmd; + /* Inside ld->peers. */ struct list_node list;