mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-07-05 00:59:19 +02:00
add deadlock mutex package
write to deadlock stderr after closing gocui more deadlock checking
This commit is contained in:
107
vendor/github.com/sasha-s/go-deadlock/stacktraces.go
generated
vendored
Normal file
107
vendor/github.com/sasha-s/go-deadlock/stacktraces.go
generated
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
package deadlock
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func callers(skip int) []uintptr {
|
||||
s := make([]uintptr, 50) // Most relevant context seem to appear near the top of the stack.
|
||||
return s[:runtime.Callers(2+skip, s)]
|
||||
}
|
||||
|
||||
func printStack(w io.Writer, stack []uintptr) {
|
||||
home := os.Getenv("HOME")
|
||||
usr, err := user.Current()
|
||||
if err == nil {
|
||||
home = usr.HomeDir
|
||||
}
|
||||
cwd, _ := os.Getwd()
|
||||
|
||||
for i, pc := range stack {
|
||||
f := runtime.FuncForPC(pc)
|
||||
name := f.Name()
|
||||
pkg := ""
|
||||
if pos := strings.LastIndex(name, "/"); pos >= 0 {
|
||||
name = name[pos+1:]
|
||||
}
|
||||
if pos := strings.Index(name, "."); pos >= 0 {
|
||||
pkg = name[:pos]
|
||||
name = name[pos+1:]
|
||||
}
|
||||
file, line := f.FileLine(pc)
|
||||
if (pkg == "runtime" && name == "goexit") || (pkg == "testing" && name == "tRunner") {
|
||||
fmt.Fprintln(w)
|
||||
return
|
||||
}
|
||||
tail := ""
|
||||
if i == 0 {
|
||||
tail = " <<<<<" // Make the line performing a lock prominent.
|
||||
}
|
||||
// Shorten the file name.
|
||||
clean := file
|
||||
if cwd != "" {
|
||||
cl, err := filepath.Rel(cwd, file)
|
||||
if err == nil {
|
||||
clean = cl
|
||||
}
|
||||
}
|
||||
if home != "" {
|
||||
s2 := strings.Replace(file, home, "~", 1)
|
||||
if len(clean) > len(s2) {
|
||||
clean = s2
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(w, "%s:%d %s.%s %s%s\n", clean, line-1, pkg, name, code(file, line), tail)
|
||||
}
|
||||
fmt.Fprintln(w)
|
||||
}
|
||||
|
||||
var fileSources struct {
|
||||
sync.Mutex
|
||||
lines map[string][][]byte
|
||||
}
|
||||
|
||||
// Reads souce file lines from disk if not cached already.
|
||||
func getSourceLines(file string) [][]byte {
|
||||
fileSources.Lock()
|
||||
defer fileSources.Unlock()
|
||||
if fileSources.lines == nil {
|
||||
fileSources.lines = map[string][][]byte{}
|
||||
}
|
||||
if lines, ok := fileSources.lines[file]; ok {
|
||||
return lines
|
||||
}
|
||||
text, _ := ioutil.ReadFile(file)
|
||||
fileSources.lines[file] = bytes.Split(text, []byte{'\n'})
|
||||
return fileSources.lines[file]
|
||||
}
|
||||
|
||||
func code(file string, line int) string {
|
||||
lines := getSourceLines(file)
|
||||
line -= 2
|
||||
if line >= len(lines) || line < 0 {
|
||||
return "???"
|
||||
}
|
||||
return "{ " + string(bytes.TrimSpace(lines[line])) + " }"
|
||||
}
|
||||
|
||||
// Stacktraces for all goroutines.
|
||||
func stacks() []byte {
|
||||
buf := make([]byte, 1024*16)
|
||||
for {
|
||||
n := runtime.Stack(buf, true)
|
||||
if n < len(buf) {
|
||||
return buf[:n]
|
||||
}
|
||||
buf = make([]byte, 2*len(buf))
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user