From 21a29d9b4d74eb1493e3a2c95b2372452d8c8649 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 30 Jun 2016 09:08:11 +0930 Subject: [PATCH] daemon: fix bug when we close two peers simulatneously. If a block triggers two peers to close, we ran io_break() on both of them; the second overrode the first and we didn't end up freeing that one. Rather than chase such bugs in future, simply iterate to see if any peers need freeing. Signed-off-by: Rusty Russell --- daemon/lightningd.c | 6 ++---- daemon/peer.c | 12 ++++++++++++ daemon/peer.h | 1 + 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/daemon/lightningd.c b/daemon/lightningd.c index bb0f4aa00..33b7e32aa 100644 --- a/daemon/lightningd.c +++ b/daemon/lightningd.c @@ -345,12 +345,10 @@ int main(int argc, char *argv[]) if (v == dstate) break; - /* We use it on a peer when it needs freeing (may be - * NULL if we only broke out due to timer). */ - tal_free(v); - if (expired) timer_expired(dstate, expired); + else + cleanup_peers(dstate); } tal_free(dstate); diff --git a/daemon/peer.c b/daemon/peer.c index d88749636..6ad1dcb91 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -2678,6 +2678,18 @@ const struct json_command getpeers_command = { "Returns a 'peers' array" }; +/* To avoid freeing underneath ourselves, we free outside event loop. */ +void cleanup_peers(struct lightningd_state *dstate) +{ + struct peer *peer, *next; + + list_for_each_safe(&dstate->peers, peer, next, list) { + /* Deletes itself from list. */ + if (!peer->conn && peer->state == STATE_CLOSED) + tal_free(peer); + } +} + /* A zero-fee single route to this peer. */ static const u8 *dummy_single_route(const tal_t *ctx, const struct peer *peer, diff --git a/daemon/peer.h b/daemon/peer.h index 5d69d162b..065d8bbbc 100644 --- a/daemon/peer.h +++ b/daemon/peer.h @@ -272,4 +272,5 @@ uint64_t commit_tx_fee(const struct bitcoin_tx *commit, void our_htlc_fulfilled(struct peer *peer, struct htlc *htlc, const struct rval *preimage); +void cleanup_peers(struct lightningd_state *dstate); #endif /* LIGHTNING_DAEMON_PEER_H */