mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-23 11:28:59 +00:00
This commit is contained in:
parent
51f65bd23a
commit
c87411851d
@ -171,11 +171,12 @@ type rawConnection struct {
|
|||||||
nextID int32
|
nextID int32
|
||||||
nextIDMut sync.Mutex
|
nextIDMut sync.Mutex
|
||||||
|
|
||||||
outbox chan asyncMessage
|
outbox chan asyncMessage
|
||||||
sendClose chan asyncMessage
|
closed chan struct{}
|
||||||
closed chan struct{}
|
closeOnce sync.Once
|
||||||
once sync.Once
|
sendCloseOnce sync.Once
|
||||||
compression Compression
|
writerExited chan struct{}
|
||||||
|
compression Compression
|
||||||
}
|
}
|
||||||
|
|
||||||
type asyncResult struct {
|
type asyncResult struct {
|
||||||
@ -216,7 +217,6 @@ func NewConnection(deviceID DeviceID, reader io.Reader, writer io.Writer, receiv
|
|||||||
cw: cw,
|
cw: cw,
|
||||||
awaiting: make(map[int32]chan asyncResult),
|
awaiting: make(map[int32]chan asyncResult),
|
||||||
outbox: make(chan asyncMessage),
|
outbox: make(chan asyncMessage),
|
||||||
sendClose: make(chan asyncMessage),
|
|
||||||
closed: make(chan struct{}),
|
closed: make(chan struct{}),
|
||||||
compression: compress,
|
compression: compress,
|
||||||
}
|
}
|
||||||
@ -643,11 +643,6 @@ func (c *rawConnection) writerLoop() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
case m := <-c.sendClose:
|
|
||||||
c.writeMessage(m)
|
|
||||||
close(m.done)
|
|
||||||
return // No message must be sent after the Close message.
|
|
||||||
|
|
||||||
case <-c.closed:
|
case <-c.closed:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -813,41 +808,38 @@ func (c *rawConnection) shouldCompressMessage(msg message) bool {
|
|||||||
// BEP message is sent before terminating the actual connection. The error
|
// BEP message is sent before terminating the actual connection. The error
|
||||||
// argument specifies the reason for closing the connection.
|
// argument specifies the reason for closing the connection.
|
||||||
func (c *rawConnection) Close(err error) {
|
func (c *rawConnection) Close(err error) {
|
||||||
c.once.Do(func() {
|
c.sendCloseOnce.Do(func() {
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
c.sendClose <- asyncMessage{&Close{err.Error()}, done}
|
c.send(&Close{err.Error()}, done)
|
||||||
<-done
|
select {
|
||||||
|
case <-done:
|
||||||
// No more sends are necessary, therefore closing the underlying
|
case <-c.closed:
|
||||||
// connection can happen at the same time as the internal cleanup.
|
}
|
||||||
// And this prevents a potential deadlock due to calling c.receiver.Closed
|
|
||||||
go c.commonClose(err)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// No more sends are necessary, therefore further steps to close the
|
||||||
|
// connection outside of this package can proceed immediately.
|
||||||
|
// And this prevents a potential deadlock due to calling c.receiver.Closed
|
||||||
|
go c.internalClose(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// internalClose is called if there is an unexpected error during normal operation.
|
// internalClose is called if there is an unexpected error during normal operation.
|
||||||
func (c *rawConnection) internalClose(err error) {
|
func (c *rawConnection) internalClose(err error) {
|
||||||
c.once.Do(func() {
|
c.closeOnce.Do(func() {
|
||||||
c.commonClose(err)
|
l.Debugln("close due to", err)
|
||||||
})
|
close(c.closed)
|
||||||
}
|
|
||||||
|
|
||||||
// commonClose is a utility function that must only be called from within
|
c.awaitingMut.Lock()
|
||||||
// rawConnection.once.Do (i.e. in Close and close).
|
for i, ch := range c.awaiting {
|
||||||
func (c *rawConnection) commonClose(err error) {
|
if ch != nil {
|
||||||
l.Debugln("close due to", err)
|
close(ch)
|
||||||
close(c.closed)
|
delete(c.awaiting, i)
|
||||||
|
}
|
||||||
c.awaitingMut.Lock()
|
|
||||||
for i, ch := range c.awaiting {
|
|
||||||
if ch != nil {
|
|
||||||
close(ch)
|
|
||||||
delete(c.awaiting, i)
|
|
||||||
}
|
}
|
||||||
}
|
c.awaitingMut.Unlock()
|
||||||
c.awaitingMut.Unlock()
|
|
||||||
|
|
||||||
c.receiver.Closed(c, err)
|
c.receiver.Closed(c, err)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// The pingSender makes sure that we've sent a message within the last
|
// The pingSender makes sure that we've sent a message within the last
|
||||||
|
Loading…
Reference in New Issue
Block a user