mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 22:45:27 +01:00
lightningd: fix crash in cancel_channel
This path is not atomic, so we can't assume channel stays around. It could be the peer closes, it could be we get a parallel fund_channel_cancel. test_funding_cancel_race caused this crash: FATAL SIGNAL 6 (version 5f0a18e) backtrace: common/daemon.c:45 (send_backtrace) 0x55c7c373a429 backtrace: common/daemon.c:53 (crashdump) 0x55c7c373a479 backtrace: (null):0 ((null)) 0x7f88ee6ddf5f backtrace: (null):0 ((null)) 0x7f88ee6dded7 backtrace: (null):0 ((null)) 0x7f88ee6bf534 backtrace: ccan/ccan/tal/tal.c:93 (call_error) 0x55c7c379427c backtrace: ccan/ccan/tal/tal.c:165 (check_bounds) 0x55c7c3794444 backtrace: ccan/ccan/tal/tal.c:174 (to_tal_hdr) 0x55c7c3794483 backtrace: ccan/ccan/tal/tal.c:186 (to_tal_hdr_or_null) 0x55c7c3794504 backtrace: ccan/ccan/tal/tal.c:421 (tal_alloc_) 0x55c7c3794c10 backtrace: ccan/ccan/tal/tal.c:466 (tal_alloc_arr_) 0x55c7c3794ded backtrace: ccan/ccan/tal/str/str.c:91 (tal_vfmt_) 0x55c7c3793560 backtrace: common/wire_error.c:22 (towire_errorfmtv) 0x55c7c3747f7b backtrace: common/wire_error.c:39 (towire_errorfmt) 0x55c7c37480a1 backtrace: lightningd/channel_control.c:635 (process_check_funding_broadcast) 0x55c7c37015bb backtrace: lightningd/bitcoind.c:558 (process_gettxout) 0x55c7c36f8e75 backtrace: lightningd/bitcoind.c:227 (bcli_finished) 0x55c7c36f8090 backtrace: ccan/ccan/io/poll.c:244 (destroy_conn) 0x55c7c37869fe backtrace: ccan/ccan/io/poll.c:250 (destroy_conn_close_fd) 0x55c7c3786a1e backtrace: ccan/ccan/tal/tal.c:235 (notify) 0x55c7c3794629 backtrace: ccan/ccan/tal/tal.c:397 (del_tree) 0x55c7c3794b18 backtrace: ccan/ccan/tal/tal.c:481 (tal_free) 0x55c7c3794ea4 backtrace: ccan/ccan/io/io.c:450 (io_close) 0x55c7c378521d backtrace: ccan/ccan/io/poll.c:449 (io_loop) 0x55c7c3787139 backtrace: lightningd/io_loop_with_timers.c:24 (io_loop_with_timers) 0x55c7c370b26d backtrace: lightningd/lightningd.c:837 (main) 0x55c7c3711661 backtrace: (null):0 ((null)) 0x7f88ee6c0b6a backtrace: (null):0 ((null)) 0x55c7c36f70b9 backtrace: (null):0 ((null)) 0xffffffffffffffff Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
794bebcc81
commit
9578fb4035
1 changed files with 30 additions and 6 deletions
|
@ -630,11 +630,31 @@ static struct channel *find_channel_by_id(const struct peer *peer,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void process_check_funding_broadcast(struct bitcoind *bitcoind UNUSED,
|
||||
/* Since this could vanish while we're checking with bitcoind, we need to save
|
||||
* the details and re-lookup.
|
||||
*
|
||||
* channel_id *should* be unique, but it can be set by the counterparty, so
|
||||
* we cannot rely on that! */
|
||||
struct channel_to_cancel {
|
||||
struct node_id peer;
|
||||
struct channel_id cid;
|
||||
};
|
||||
|
||||
static void process_check_funding_broadcast(struct bitcoind *bitcoind,
|
||||
const struct bitcoin_tx_output *txout,
|
||||
void *arg)
|
||||
{
|
||||
struct channel *cancel = arg;
|
||||
struct channel_to_cancel *cc = arg;
|
||||
struct peer *peer;
|
||||
struct channel *cancel;
|
||||
|
||||
/* Peer could have errored out while we were waiting */
|
||||
peer = peer_by_id(bitcoind->ld, &cc->peer);
|
||||
if (!peer)
|
||||
return;
|
||||
cancel = find_channel_by_id(peer, &cc->cid);
|
||||
if (!cancel)
|
||||
return;
|
||||
|
||||
if (txout != NULL) {
|
||||
for (size_t i = 0; i < tal_count(cancel->forgets); i++)
|
||||
|
@ -662,7 +682,9 @@ struct command_result *cancel_channel_before_broadcast(struct command *cmd,
|
|||
const jsmntok_t *cidtok)
|
||||
{
|
||||
struct channel *cancel_channel;
|
||||
struct channel_to_cancel *cc = tal(cmd, struct channel_to_cancel);
|
||||
|
||||
cc->peer = peer->id;
|
||||
if (!cidtok) {
|
||||
struct channel *channel;
|
||||
|
||||
|
@ -678,13 +700,15 @@ struct command_result *cancel_channel_before_broadcast(struct command *cmd,
|
|||
if (!cancel_channel)
|
||||
return command_fail(cmd, LIGHTNINGD,
|
||||
"No channels matching that peer_id");
|
||||
derive_channel_id(&cc->cid,
|
||||
&cancel_channel->funding_txid,
|
||||
cancel_channel->funding_outnum);
|
||||
} else {
|
||||
struct channel_id cid;
|
||||
if (!json_tok_channel_id(buffer, cidtok, &cid))
|
||||
if (!json_tok_channel_id(buffer, cidtok, &cc->cid))
|
||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"Invalid channel_id parameter.");
|
||||
|
||||
cancel_channel = find_channel_by_id(peer, &cid);
|
||||
cancel_channel = find_channel_by_id(peer, &cc->cid);
|
||||
if (!cancel_channel)
|
||||
return command_fail(cmd, LIGHTNINGD,
|
||||
"Channel ID not found: '%.*s'",
|
||||
|
@ -721,6 +745,6 @@ struct command_result *cancel_channel_before_broadcast(struct command *cmd,
|
|||
&cancel_channel->funding_txid,
|
||||
cancel_channel->funding_outnum,
|
||||
process_check_funding_broadcast,
|
||||
cancel_channel);
|
||||
notleak(cc));
|
||||
return command_still_pending(cmd);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue