mirror of
https://github.com/rclone/rclone.git
synced 2024-12-23 15:38:57 +01:00
accounting: fix locking in Transfer to avoid deadlock with --progress
Before this change, using -P occasionally deadlocked on the Transfer
mutex when Transfer.Done() was called with a non nil error and the
StatsInfo mutex since they mutually call each other.
This was fixed by making sure that the Transfer mutex is always
released before calling any StatsInfo methods.
This improves on: 6f87267b34
Fixes #3505
This commit is contained in:
parent
ffa1dac10b
commit
cf9b973fe4
@ -48,6 +48,10 @@ type Transfer struct {
|
||||
checking bool
|
||||
|
||||
// Protects all below
|
||||
//
|
||||
// NB to avoid deadlocks we must release this lock before
|
||||
// calling any methods on Transfer.stats. This is because
|
||||
// StatsInfo calls back into Transfer.
|
||||
mu sync.RWMutex
|
||||
acc *Account
|
||||
err error
|
||||
@ -79,20 +83,26 @@ func newTransferRemoteSize(stats *StatsInfo, remote string, size int64, checking
|
||||
// Done ends the transfer.
|
||||
// Must be called after transfer is finished to run proper cleanups.
|
||||
func (tr *Transfer) Done(err error) {
|
||||
tr.mu.Lock()
|
||||
|
||||
if err != nil {
|
||||
tr.stats.Error(err)
|
||||
|
||||
tr.mu.Lock()
|
||||
tr.err = err
|
||||
tr.mu.Unlock()
|
||||
}
|
||||
if tr.acc != nil {
|
||||
if err := tr.acc.Close(); err != nil {
|
||||
|
||||
tr.mu.RLock()
|
||||
acc := tr.acc
|
||||
tr.mu.RUnlock()
|
||||
|
||||
if acc != nil {
|
||||
if err := acc.Close(); err != nil {
|
||||
fs.LogLevelPrintf(fs.Config.StatsLogLevel, nil, "can't close account: %+v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
tr.mu.Lock()
|
||||
tr.completedAt = time.Now()
|
||||
|
||||
tr.mu.Unlock()
|
||||
|
||||
if tr.checking {
|
||||
|
Loading…
Reference in New Issue
Block a user