-
Notifications
You must be signed in to change notification settings - Fork 913
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
connectd: fix accidental handling of old reconnections. #5256
Merged
rustyrussell
merged 3 commits into
ElementsProject:master
from
rustyrussell:guilt/connectd-cleanups
May 16, 2022
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -211,36 +211,29 @@ static void peer_connected_in(struct daemon *daemon, | |
tal_free(connect); | ||
} | ||
|
||
/*~ This is an ad-hoc marshalling structure where we store arguments so we | ||
* can call peer_connected again. */ | ||
struct peer_reconnected { | ||
struct daemon *daemon; | ||
struct node_id id; | ||
struct wireaddr_internal addr; | ||
const struct wireaddr *remote_addr; | ||
struct crypto_state cs; | ||
const u8 *their_features; | ||
bool incoming; | ||
}; | ||
|
||
/*~ For simplicity, lightningd only ever deals with a single connection per | ||
* peer. So if we already know about a peer, we tell lightning to disconnect | ||
* the old one and retry once it does. */ | ||
static struct io_plan *retry_peer_connected(struct io_conn *conn, | ||
struct peer_reconnected *pr) | ||
{ | ||
struct io_plan *plan; | ||
|
||
/*~ As you can see, we've had issues with this code before :( */ | ||
status_peer_debug(&pr->id, "processing now old peer gone"); | ||
|
||
/*~ Usually the pattern is to return this directly, but we have to free | ||
* our temporary structure. */ | ||
plan = peer_connected(conn, pr->daemon, &pr->id, &pr->addr, | ||
/* If this fails (still waiting), pr will be freed, so reparent onto | ||
* tmpctx so it gets freed either way. */ | ||
tal_steal(tmpctx, pr); | ||
|
||
/*~ Usually the pattern is to return this directly. */ | ||
return peer_connected(conn, pr->daemon, &pr->id, &pr->addr, | ||
pr->remote_addr, | ||
&pr->cs, take(pr->their_features), pr->incoming); | ||
tal_free(pr); | ||
return plan; | ||
} | ||
|
||
/*~ A common use for destructors is to remove themselves from a data structure */ | ||
static void destroy_peer_reconnected(struct peer_reconnected *pr) | ||
{ | ||
peer_reconnected_htable_del(&pr->daemon->reconnected, pr); | ||
} | ||
|
||
/*~ If we already know about this peer, we tell lightningd and it disconnects | ||
|
@@ -259,6 +252,13 @@ static struct io_plan *peer_reconnected(struct io_conn *conn, | |
|
||
status_peer_debug(id, "reconnect"); | ||
|
||
/* If we have a previous reconnection, we replace it. */ | ||
pr = peer_reconnected_htable_get(&daemon->reconnected, id); | ||
if (pr) { | ||
peer_reconnected_htable_del(&daemon->reconnected, pr); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the previous reconnection already had the destructor installed, would it not delete this twice? Or delete from |
||
tal_free(pr); | ||
} | ||
|
||
/* Tell master to kill it: will send peer_disconnect */ | ||
msg = towire_connectd_reconnected(NULL, id); | ||
daemon_conn_send(daemon->master, take(msg)); | ||
|
@@ -271,6 +271,8 @@ static struct io_plan *peer_reconnected(struct io_conn *conn, | |
pr->addr = *addr; | ||
pr->remote_addr = tal_dup_or_null(pr, struct wireaddr, remote_addr); | ||
pr->incoming = incoming; | ||
peer_reconnected_htable_add(&daemon->reconnected, pr); | ||
tal_add_destructor(pr, destroy_peer_reconnected); | ||
|
||
/*~ Note that tal_dup_talarr() will do handle the take() of features | ||
* (turning it into a simply tal_steal() in those cases). */ | ||
|
@@ -280,11 +282,7 @@ static struct io_plan *peer_reconnected(struct io_conn *conn, | |
* the peer set. When someone calls `io_wake()` on that address, it | ||
* will call retry_peer_connected above. */ | ||
return io_wait(conn, peer_htable_get(&daemon->peers, id), | ||
/*~ The notleak() wrapper is a DEVELOPER-mode hack so | ||
* that our memory leak detection doesn't consider 'pr' | ||
* (which is not referenced from our code) to be a | ||
* memory leak. */ | ||
retry_peer_connected, notleak(pr)); | ||
retry_peer_connected, pr); | ||
} | ||
|
||
/*~ When we free a peer, we remove it from the daemon's hashtable */ | ||
|
@@ -1902,7 +1900,6 @@ void peer_conn_closed(struct peer *peer) | |
struct connecting *connect = find_connecting(peer->daemon, &peer->id); | ||
|
||
/* These should be closed already! */ | ||
assert(tal_count(peer->subds) == 0); | ||
assert(!peer->to_peer); | ||
assert(peer->ready_to_die || !peer->active); | ||
|
||
|
@@ -1981,6 +1978,7 @@ static void dev_connect_memleak(struct daemon *daemon, const u8 *msg) | |
/* Now delete daemon and those which it has pointers to. */ | ||
memleak_remove_region(memtable, daemon, sizeof(daemon)); | ||
memleak_remove_htable(memtable, &daemon->peers.raw); | ||
memleak_remove_htable(memtable, &daemon->reconnected.raw); | ||
|
||
found_leak = dump_memleak(memtable, memleak_status_broken); | ||
daemon_conn_send(daemon->master, | ||
|
@@ -2127,6 +2125,7 @@ int main(int argc, char *argv[]) | |
/* Allocate and set up our simple top-level structure. */ | ||
daemon = tal(NULL, struct daemon); | ||
peer_htable_init(&daemon->peers); | ||
peer_reconnected_htable_init(&daemon->reconnected); | ||
memleak_add_helper(daemon, memleak_daemon_cb); | ||
list_head_init(&daemon->connecting); | ||
timers_init(&daemon->timers, time_mono()); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be #5254 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, these refer to the PR, not the bug itself...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah damnt! Sorry just assuming wrong stuff