From dd3d7467c3db1a618ab38ccf1fb2450b4a1723de Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Tue, 28 Jan 2014 14:09:19 -0500 Subject: [PATCH] Fixes for writeDirtyToDisk. This commit fixes two issues in the writeDirtyToDisk function: First, closing the temporary files is now done using a defer, so they are always closed. Second, the various account mutexs are no longer unlocked using a defer, preventing more than one from being held at once and causing a deadlock caused by incorrect locking order. --- disksync.go | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/disksync.go b/disksync.go index b8c03d8..33fa95b 100644 --- a/disksync.go +++ b/disksync.go @@ -217,20 +217,22 @@ func (a *Account) writeDirtyToDisk() error { if err != nil { return err } + defer tmpfile.Close() - a.UtxoStore.Lock() - defer a.UtxoStore.Unlock() - - if _, err = a.UtxoStore.s.WriteTo(tmpfile); err != nil { + a.UtxoStore.RLock() + _, err = a.UtxoStore.s.WriteTo(tmpfile) + a.UtxoStore.RUnlock() + if err != nil { return err } - tmpfile.Close() if err = Rename(tmpfile.Name(), utxofilepath); err != nil { return err } + a.UtxoStore.Lock() a.UtxoStore.dirty = false + a.UtxoStore.Unlock() } // Transactions @@ -243,20 +245,22 @@ func (a *Account) writeDirtyToDisk() error { if err != nil { return err } + defer tmpfile.Close() - a.TxStore.Lock() - defer a.TxStore.Unlock() - - if _, err = a.TxStore.s.WriteTo(tmpfile); err != nil { + a.TxStore.RLock() + _, err = a.TxStore.s.WriteTo(tmpfile) + a.TxStore.RUnlock() + if err != nil { return err } - tmpfile.Close() if err = Rename(tmpfile.Name(), txfilepath); err != nil { return err } + a.TxStore.Lock() a.TxStore.dirty = false + a.TxStore.Unlock() } // Wallet @@ -269,20 +273,22 @@ func (a *Account) writeDirtyToDisk() error { if err != nil { return err } + defer tmpfile.Close() - a.mtx.Lock() - defer a.mtx.Unlock() - - if _, err = a.WriteTo(tmpfile); err != nil { + a.mtx.RLock() + _, err = a.Wallet.WriteTo(tmpfile) + a.mtx.RUnlock() + if err != nil { return err } - tmpfile.Close() if err = Rename(tmpfile.Name(), wfilepath); err != nil { return err } + a.mtx.Lock() a.dirty = false + a.mtx.Unlock() } return nil