From 9ef67e50ffef669a32c336e0ad6406a36b8ec297 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 9 Oct 2018 19:18:52 +1030 Subject: [PATCH] lightningd: don't leave htlc_out's in pointer dangling when htlc_in freed. Now we know this can happen (see previous patch), we need to handle it. Signed-off-by: Rusty Russell --- lightningd/htlc_end.c | 25 ++++++++++++++++++++++++- lightningd/htlc_end.h | 3 +++ lightningd/peer_htlcs.c | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/lightningd/htlc_end.c b/lightningd/htlc_end.c index 708b4fa47..6a775f0e6 100644 --- a/lightningd/htlc_end.c +++ b/lightningd/htlc_end.c @@ -213,6 +213,27 @@ struct htlc_out *htlc_out_check(const struct htlc_out *hout, return cast_const(struct htlc_out *, hout); } +static void htlc_out_clear_hin(struct htlc_in *hin, struct htlc_out *hout) +{ + assert(hout->in == hin); + hout->in = NULL; +} + +static void destroy_htlc_out_with_hin(struct htlc_out *hout) +{ + /* Don't try to clear our ptr if we're freed before hin! */ + if (hout->in) + tal_del_destructor2(hout->in, htlc_out_clear_hin, hout); +} + +void htlc_out_connect_htlc_in(struct htlc_out *hout, struct htlc_in *hin) +{ + assert(!hout->in); + hout->in = hin; + tal_add_destructor2(hin, htlc_out_clear_hin, hout); + tal_add_destructor(hout, destroy_htlc_out_with_hin); +} + /* You need to set the ID, then connect_htlc_out this! */ struct htlc_out *new_htlc_out(const tal_t *ctx, struct channel *channel, @@ -241,7 +262,9 @@ struct htlc_out *new_htlc_out(const tal_t *ctx, hout->preimage = NULL; hout->local = local; - hout->in = in; + hout->in = NULL; + if (in) + htlc_out_connect_htlc_in(hout, in); return htlc_out_check(hout, "new_htlc_out"); } diff --git a/lightningd/htlc_end.h b/lightningd/htlc_end.h index e8fd8912f..4660c081d 100644 --- a/lightningd/htlc_end.h +++ b/lightningd/htlc_end.h @@ -138,6 +138,9 @@ struct htlc_out *new_htlc_out(const tal_t *ctx, void connect_htlc_in(struct htlc_in_map *map, struct htlc_in *hin); void connect_htlc_out(struct htlc_out_map *map, struct htlc_out *hout); +/* Set up hout->in to be hin (non-NULL), and clear if hin freed. */ +void htlc_out_connect_htlc_in(struct htlc_out *hout, struct htlc_in *hin); + struct htlc_out *htlc_out_check(const struct htlc_out *hout, const char *abortstr); struct htlc_in *htlc_in_check(const struct htlc_in *hin, const char *abortstr); diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 68f893d97..535d0a01c 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -1712,7 +1712,7 @@ void htlcs_reconnect(struct lightningd *ld, "Found corresponding htlc_in %" PRIu64 " for htlc_out %" PRIu64, hin->dbid, hout->dbid); - hout->in = hin; + htlc_out_connect_htlc_in(hout, hin); break; } }