Fix deadlock on rewrite of opHistory when history limit is reached (#69)

It is possible for `opHistory.Rewrite` to be called from
`opHistory.historyUpdatePath`. This is problematic, because both methods
grab a lock, and Mutexes in go are not reentrant. This change pulls out
the logic in Rewrite into `opHistory.rewriteLocked`, and retains the
public facing method.
This commit is contained in:
Nathan VanBenschoten 2016-08-11 22:11:21 -04:00 committed by chzyer
parent c144c8dde4
commit a193146c91
1 changed files with 7 additions and 3 deletions

View File

@ -5,8 +5,8 @@ import (
"container/list"
"fmt"
"os"
"sync"
"strings"
"sync"
)
type hisItem struct {
@ -26,7 +26,7 @@ type opHistory struct {
historyVer int64
current *list.Element
fd *os.File
fdLock sync.Mutex
fdLock sync.Mutex
}
func newOpHistory(cfg *Config) (o *opHistory) {
@ -85,7 +85,7 @@ func (o *opHistory) historyUpdatePath(path string) {
o.Compact()
}
if total > o.cfg.HistoryLimit {
o.Rewrite()
o.rewriteLocked()
}
o.historyVer++
o.Push(nil)
@ -101,6 +101,10 @@ func (o *opHistory) Compact() {
func (o *opHistory) Rewrite() {
o.fdLock.Lock()
defer o.fdLock.Unlock()
o.rewriteLocked()
}
func (o *opHistory) rewriteLocked() {
if o.cfg.HistoryFile == "" {
return
}