Improve link setup locking and guards

This commit is contained in:
Neil Alexander 2023-05-23 22:39:10 +01:00
parent 06ca8941c7
commit 2eda59d9e4
No known key found for this signature in database
GPG Key ID: A02A2019A2BB0944

View File

@ -267,6 +267,11 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
// Update the link state with our newly wrapped connection. // Update the link state with our newly wrapped connection.
// Clear the error state. // Clear the error state.
state.Lock() state.Lock()
if state._conn != nil {
// If a peering has come up in this time, abort this one.
state.Unlock()
return
}
state._conn = lc state._conn = lc
state.Unlock() state.Unlock()
@ -366,18 +371,6 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
// connection. This prevents duplicate peerings. // connection. This prevents duplicate peerings.
l.Lock() l.Lock()
state, ok := l._links[info] state, ok := l._links[info]
if ok && state != nil {
switch {
case state._conn != nil:
// We are already connected to something.
case state._conn == nil && state._errtime == time.Time{}:
// We aren't connected yet, but the fact that there
// is no last error suggests we haven't yet attempted
// an outbound connection at all.
l.Unlock()
return
}
}
if !ok || state == nil { if !ok || state == nil {
state = &link{ state = &link{
linkType: linkTypeIncoming, linkType: linkTypeIncoming,
@ -385,6 +378,14 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
kick: make(chan struct{}), kick: make(chan struct{}),
} }
} }
state.Lock()
if state._conn != nil {
// If a connection has come up in this time, abort
// this one.
state.Unlock()
l.Unlock()
return
}
// The linkConn wrapper allows us to track the number of // The linkConn wrapper allows us to track the number of
// bytes written to and read from this connection without // bytes written to and read from this connection without
@ -396,7 +397,6 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
// Update the link state with our newly wrapped connection. // Update the link state with our newly wrapped connection.
// Clear the error state. // Clear the error state.
state.Lock()
state._conn = lc state._conn = lc
state._err = nil state._err = nil
state._errtime = time.Time{} state._errtime = time.Time{}