mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-08-06 11:02:41 +03:00
go-deadlock version bump to fix crash with go 1.23
This commit is contained in:
122
vendor/github.com/sasha-s/go-deadlock/deadlock.go
generated
vendored
122
vendor/github.com/sasha-s/go-deadlock/deadlock.go
generated
vendored
@@ -21,7 +21,7 @@ var Opts = struct {
|
||||
// Would disable lock order based deadlock detection if DisableLockOrderDetection == true.
|
||||
DisableLockOrderDetection bool
|
||||
// Waiting for a lock for longer than DeadlockTimeout is considered a deadlock.
|
||||
// Ignored is DeadlockTimeout <= 0.
|
||||
// Ignored if DeadlockTimeout <= 0.
|
||||
DeadlockTimeout time.Duration
|
||||
// OnPotentialDeadlock is called each time a potential deadlock is detected -- either based on
|
||||
// lock order or on lock wait time.
|
||||
@@ -69,6 +69,9 @@ type WaitGroup struct {
|
||||
sync.WaitGroup
|
||||
}
|
||||
|
||||
// NewCond is a sync.NewCond wrapper
|
||||
var NewCond = sync.NewCond
|
||||
|
||||
// A Mutex is a drop-in replacement for sync.Mutex.
|
||||
// Performs deadlock detection unless disabled in Opts.
|
||||
type Mutex struct {
|
||||
@@ -179,54 +182,7 @@ func lock(lockFn func(), ptr interface{}) {
|
||||
} else {
|
||||
ch := make(chan struct{})
|
||||
currentID := goid.Get()
|
||||
go func() {
|
||||
for {
|
||||
t := time.NewTimer(Opts.DeadlockTimeout)
|
||||
defer t.Stop() // This runs after the losure finishes, but it's OK.
|
||||
select {
|
||||
case <-t.C:
|
||||
lo.mu.Lock()
|
||||
prev, ok := lo.cur[ptr]
|
||||
if !ok {
|
||||
lo.mu.Unlock()
|
||||
break // Nobody seems to be holding the lock, try again.
|
||||
}
|
||||
Opts.mu.Lock()
|
||||
fmt.Fprintln(Opts.LogBuf, header)
|
||||
fmt.Fprintln(Opts.LogBuf, "Previous place where the lock was grabbed")
|
||||
fmt.Fprintf(Opts.LogBuf, "goroutine %v lock %p\n", prev.gid, ptr)
|
||||
printStack(Opts.LogBuf, prev.stack)
|
||||
fmt.Fprintln(Opts.LogBuf, "Have been trying to lock it again for more than", Opts.DeadlockTimeout)
|
||||
fmt.Fprintf(Opts.LogBuf, "goroutine %v lock %p\n", currentID, ptr)
|
||||
printStack(Opts.LogBuf, stack)
|
||||
stacks := stacks()
|
||||
grs := bytes.Split(stacks, []byte("\n\n"))
|
||||
for _, g := range grs {
|
||||
if goid.ExtractGID(g) == prev.gid {
|
||||
fmt.Fprintln(Opts.LogBuf, "Here is what goroutine", prev.gid, "doing now")
|
||||
Opts.LogBuf.Write(g)
|
||||
fmt.Fprintln(Opts.LogBuf)
|
||||
}
|
||||
}
|
||||
lo.other(ptr)
|
||||
if Opts.PrintAllCurrentGoroutines {
|
||||
fmt.Fprintln(Opts.LogBuf, "All current goroutines:")
|
||||
Opts.LogBuf.Write(stacks)
|
||||
}
|
||||
fmt.Fprintln(Opts.LogBuf)
|
||||
if buf, ok := Opts.LogBuf.(*bufio.Writer); ok {
|
||||
buf.Flush()
|
||||
}
|
||||
Opts.mu.Unlock()
|
||||
lo.mu.Unlock()
|
||||
Opts.OnPotentialDeadlock()
|
||||
<-ch
|
||||
return
|
||||
case <-ch:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
go checkDeadlock(stack, ptr, currentID, ch)
|
||||
lockFn()
|
||||
postLock(stack, ptr)
|
||||
close(ch)
|
||||
@@ -235,6 +191,74 @@ func lock(lockFn func(), ptr interface{}) {
|
||||
postLock(stack, ptr)
|
||||
}
|
||||
|
||||
var timersPool sync.Pool
|
||||
|
||||
func acquireTimer(d time.Duration) *time.Timer {
|
||||
t, ok := timersPool.Get().(*time.Timer)
|
||||
if ok {
|
||||
_ = t.Reset(d)
|
||||
return t
|
||||
}
|
||||
return time.NewTimer(Opts.DeadlockTimeout)
|
||||
}
|
||||
|
||||
func releaseTimer(t *time.Timer) {
|
||||
if !t.Stop() {
|
||||
<-t.C
|
||||
}
|
||||
timersPool.Put(t)
|
||||
}
|
||||
|
||||
func checkDeadlock(stack []uintptr, ptr interface{}, currentID int64, ch <-chan struct{}) {
|
||||
t := acquireTimer(Opts.DeadlockTimeout)
|
||||
defer releaseTimer(t)
|
||||
for {
|
||||
select {
|
||||
case <-t.C:
|
||||
lo.mu.Lock()
|
||||
prev, ok := lo.cur[ptr]
|
||||
if !ok {
|
||||
lo.mu.Unlock()
|
||||
break // Nobody seems to be holding the lock, try again.
|
||||
}
|
||||
Opts.mu.Lock()
|
||||
fmt.Fprintln(Opts.LogBuf, header)
|
||||
fmt.Fprintln(Opts.LogBuf, "Previous place where the lock was grabbed")
|
||||
fmt.Fprintf(Opts.LogBuf, "goroutine %v lock %p\n", prev.gid, ptr)
|
||||
printStack(Opts.LogBuf, prev.stack)
|
||||
fmt.Fprintln(Opts.LogBuf, "Have been trying to lock it again for more than", Opts.DeadlockTimeout)
|
||||
fmt.Fprintf(Opts.LogBuf, "goroutine %v lock %p\n", currentID, ptr)
|
||||
printStack(Opts.LogBuf, stack)
|
||||
stacks := stacks()
|
||||
grs := bytes.Split(stacks, []byte("\n\n"))
|
||||
for _, g := range grs {
|
||||
if goid.ExtractGID(g) == prev.gid {
|
||||
fmt.Fprintln(Opts.LogBuf, "Here is what goroutine", prev.gid, "doing now")
|
||||
Opts.LogBuf.Write(g)
|
||||
fmt.Fprintln(Opts.LogBuf)
|
||||
}
|
||||
}
|
||||
lo.other(ptr)
|
||||
if Opts.PrintAllCurrentGoroutines {
|
||||
fmt.Fprintln(Opts.LogBuf, "All current goroutines:")
|
||||
Opts.LogBuf.Write(stacks)
|
||||
}
|
||||
fmt.Fprintln(Opts.LogBuf)
|
||||
if buf, ok := Opts.LogBuf.(*bufio.Writer); ok {
|
||||
buf.Flush()
|
||||
}
|
||||
Opts.mu.Unlock()
|
||||
lo.mu.Unlock()
|
||||
Opts.OnPotentialDeadlock()
|
||||
<-ch
|
||||
return
|
||||
case <-ch:
|
||||
return
|
||||
}
|
||||
t.Reset(Opts.DeadlockTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
type lockOrder struct {
|
||||
mu sync.Mutex
|
||||
cur map[interface{}]stackGID // stacktraces + gids for the locks currently taken.
|
||||
|
Reference in New Issue
Block a user