mirror of
https://github.com/octoleo/syncthing.git
synced 2025-01-11 10:38:16 +00:00
This commit is contained in:
parent
51f65bd23a
commit
c87411851d
@ -172,9 +172,10 @@ type rawConnection struct {
|
|||||||
nextIDMut sync.Mutex
|
nextIDMut sync.Mutex
|
||||||
|
|
||||||
outbox chan asyncMessage
|
outbox chan asyncMessage
|
||||||
sendClose chan asyncMessage
|
|
||||||
closed chan struct{}
|
closed chan struct{}
|
||||||
once sync.Once
|
closeOnce sync.Once
|
||||||
|
sendCloseOnce sync.Once
|
||||||
|
writerExited chan struct{}
|
||||||
compression Compression
|
compression Compression
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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,28 +808,24 @@ 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)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// commonClose is a utility function that must only be called from within
|
|
||||||
// rawConnection.once.Do (i.e. in Close and close).
|
|
||||||
func (c *rawConnection) commonClose(err error) {
|
|
||||||
l.Debugln("close due to", err)
|
l.Debugln("close due to", err)
|
||||||
close(c.closed)
|
close(c.closed)
|
||||||
|
|
||||||
@ -848,6 +839,7 @@ func (c *rawConnection) commonClose(err error) {
|
|||||||
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