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" "container/list"
"fmt" "fmt"
"os" "os"
"sync"
"strings" "strings"
"sync"
) )
type hisItem struct { type hisItem struct {
@ -85,7 +85,7 @@ func (o *opHistory) historyUpdatePath(path string) {
o.Compact() o.Compact()
} }
if total > o.cfg.HistoryLimit { if total > o.cfg.HistoryLimit {
o.Rewrite() o.rewriteLocked()
} }
o.historyVer++ o.historyVer++
o.Push(nil) o.Push(nil)
@ -101,6 +101,10 @@ func (o *opHistory) Compact() {
func (o *opHistory) Rewrite() { func (o *opHistory) Rewrite() {
o.fdLock.Lock() o.fdLock.Lock()
defer o.fdLock.Unlock() defer o.fdLock.Unlock()
o.rewriteLocked()
}
func (o *opHistory) rewriteLocked() {
if o.cfg.HistoryFile == "" { if o.cfg.HistoryFile == "" {
return return
} }