Package: syncthing
Version: 1.12.1~ds1-2
Severity: important

As discussed on the go-team mailing list [1], I am filing this bug to
address an important fix in upstream since the version to be included in
stable.

An error in the database can lead to a dead-lock in the index-sender.

The patch fixing this is attached.

[1]: https://lists.debian.org/debian-go/2021/02/msg00067.html
>From 6eed8ef5f0e253878221546afe395af103b1d43b Mon Sep 17 00:00:00 2001
From: Simon Frei <[email protected]>
Date: Wed, 30 Dec 2020 09:59:11 +0100
Subject: [PATCH 3/4] lib/model: Handle index sender terminating due to error
 (fixes #7231) (#7232)

---
 lib/model/indexsender.go | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/lib/model/indexsender.go b/lib/model/indexsender.go
index 7bca77447..1883a7e83 100644
--- a/lib/model/indexsender.go
+++ b/lib/model/indexsender.go
@@ -30,6 +30,7 @@ type indexSender struct {
 	prevSequence             int64
 	evLogger                 events.Logger
 	connClosed               chan struct{}
+	done                     chan struct{}
 	token                    suture.ServiceToken
 	pauseChan                chan struct{}
 	resumeChan               chan *db.FileSet
@@ -38,6 +39,7 @@ type indexSender struct {
 func (s *indexSender) Serve(ctx context.Context) (err error) {
 	l.Debugf("Starting indexSender for %s to %s at %s (slv=%d)", s.folder, s.conn.ID(), s.conn, s.prevSequence)
 	defer func() {
+		close(s.done)
 		err = util.NoRestartErr(err)
 		l.Debugf("Exiting indexSender for %s to %s at %s: %v", s.folder, s.conn.ID(), s.conn, err)
 	}()
@@ -101,14 +103,14 @@ func (s *indexSender) Serve(ctx context.Context) (err error) {
 
 func (s *indexSender) resume(fset *db.FileSet) {
 	select {
-	case <-s.connClosed:
+	case <-s.done:
 	case s.resumeChan <- fset:
 	}
 }
 
 func (s *indexSender) pause() {
 	select {
-	case <-s.connClosed:
+	case <-s.done:
 	case s.pauseChan <- struct{}{}:
 	}
 }
@@ -314,6 +316,7 @@ func (r *indexSenderRegistry) addLocked(folder config.FolderConfiguration, fset
 	is := &indexSender{
 		conn:                     r.conn,
 		connClosed:               r.closed,
+		done:                     make(chan struct{}),
 		folder:                   folder.ID,
 		folderIsReceiveEncrypted: folder.Type == config.FolderTypeReceiveEncrypted,
 		fset:                     fset,
@@ -366,7 +369,7 @@ func (r *indexSenderRegistry) removeAllExcept(except map[string]struct{}) {
 			delete(r.indexSenders, folder)
 		}
 	}
-	for folder := range r.indexSenders {
+	for folder := range r.startInfos {
 		if _, ok := except[folder]; !ok {
 			delete(r.startInfos, folder)
 		}
-- 
2.30.0

Reply via email to