mirror of
https://github.com/restic/restic.git
synced 2024-12-23 00:07:25 +00:00
backup: Fix deadlock
When the archiver is faster than the scanner, restic deadlocks. This commit adds a `finished` channel to the struct in `ui/backup.go` so that scanner results are ignored when the archiver is already finished. Closes #1834
This commit is contained in:
parent
ab37c6095a
commit
c44e808aa5
2 changed files with 14 additions and 5 deletions
|
@ -58,6 +58,9 @@ func (s *Scanner) Scan(ctx context.Context, targets []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
s.Result("", stats)
|
s.Result("", stats)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -107,6 +110,9 @@ func (s *Scanner) scan(ctx context.Context, stats ScanStats, target string) (Sca
|
||||||
stats.Others++
|
stats.Others++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return stats, ctx.Err()
|
||||||
|
}
|
||||||
s.Result(target, stats)
|
s.Result(target, stats)
|
||||||
return stats, nil
|
return stats, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ type Backup struct {
|
||||||
processedCh chan counter
|
processedCh chan counter
|
||||||
errCh chan struct{}
|
errCh chan struct{}
|
||||||
workerCh chan fileWorkerMessage
|
workerCh chan fileWorkerMessage
|
||||||
clearStatus chan struct{}
|
finished chan struct{}
|
||||||
|
|
||||||
summary struct {
|
summary struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
@ -69,7 +69,7 @@ func NewBackup(term *termstatus.Terminal, verbosity uint) *Backup {
|
||||||
processedCh: make(chan counter),
|
processedCh: make(chan counter),
|
||||||
errCh: make(chan struct{}),
|
errCh: make(chan struct{}),
|
||||||
workerCh: make(chan fileWorkerMessage),
|
workerCh: make(chan fileWorkerMessage),
|
||||||
clearStatus: make(chan struct{}),
|
finished: make(chan struct{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ func (b *Backup) Run(ctx context.Context) error {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return nil
|
return nil
|
||||||
case <-b.clearStatus:
|
case <-b.finished:
|
||||||
started = false
|
started = false
|
||||||
b.term.SetStatus([]string{""})
|
b.term.SetStatus([]string{""})
|
||||||
case t, ok := <-b.totalCh:
|
case t, ok := <-b.totalCh:
|
||||||
|
@ -333,7 +333,10 @@ func (b *Backup) CompleteItemFn(item string, previous, current *restic.Node, s a
|
||||||
|
|
||||||
// ReportTotal sets the total stats up to now
|
// ReportTotal sets the total stats up to now
|
||||||
func (b *Backup) ReportTotal(item string, s archiver.ScanStats) {
|
func (b *Backup) ReportTotal(item string, s archiver.ScanStats) {
|
||||||
b.totalCh <- counter{Files: s.Files, Dirs: s.Dirs, Bytes: s.Bytes}
|
select {
|
||||||
|
case b.totalCh <- counter{Files: s.Files, Dirs: s.Dirs, Bytes: s.Bytes}:
|
||||||
|
case <-b.finished:
|
||||||
|
}
|
||||||
|
|
||||||
if item == "" {
|
if item == "" {
|
||||||
b.V("scan finished in %.3fs: %v files, %s",
|
b.V("scan finished in %.3fs: %v files, %s",
|
||||||
|
@ -347,7 +350,7 @@ func (b *Backup) ReportTotal(item string, s archiver.ScanStats) {
|
||||||
|
|
||||||
// Finish prints the finishing messages.
|
// Finish prints the finishing messages.
|
||||||
func (b *Backup) Finish() {
|
func (b *Backup) Finish() {
|
||||||
b.clearStatus <- struct{}{}
|
close(b.finished)
|
||||||
|
|
||||||
b.P("\n")
|
b.P("\n")
|
||||||
b.P("Files: %5d new, %5d changed, %5d unmodified\n", b.summary.Files.New, b.summary.Files.Changed, b.summary.Files.Unchanged)
|
b.P("Files: %5d new, %5d changed, %5d unmodified\n", b.summary.Files.New, b.summary.Files.Changed, b.summary.Files.Unchanged)
|
||||||
|
|
Loading…
Reference in a new issue