mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-10 07:36:27 -04:00
Bumps [github.com/sasha-s/go-deadlock](https://github.com/sasha-s/go-deadlock) from 0.3.6 to 0.3.9. - [Release notes](https://github.com/sasha-s/go-deadlock/releases) - [Commits](https://github.com/sasha-s/go-deadlock/compare/v0.3.6...v0.3.9) --- updated-dependencies: - dependency-name: github.com/sasha-s/go-deadlock dependency-version: 0.3.9 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
137 lines
3.1 KiB
Go
137 lines
3.1 KiB
Go
package deadlock
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/user"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
const stackBufSize = 50
|
|
|
|
var stackBufPool = sync.Pool{
|
|
New: func() interface{} {
|
|
return new([stackBufSize]uintptr)
|
|
},
|
|
}
|
|
|
|
// callers returns a stack trace backed by a pooled buffer. The caller must
|
|
// eventually return buf via releaseStackBuf — typically through the
|
|
// postLock/postUnlock path which stores it in stackGID.buf.
|
|
func callers(skip int) ([]uintptr, *[stackBufSize]uintptr) {
|
|
buf := stackBufPool.Get().(*[stackBufSize]uintptr)
|
|
n := runtime.Callers(2+skip, buf[:])
|
|
return buf[:n], buf
|
|
}
|
|
|
|
// releaseStackBuf returns a pooled stack buffer obtained from callers(). Safe to
|
|
// call with nil (e.g. when the buffer was already handed off via stackGID.buf).
|
|
func releaseStackBuf(buf *[stackBufSize]uintptr) {
|
|
if buf != nil {
|
|
stackBufPool.Put(buf)
|
|
}
|
|
}
|
|
|
|
// copyStack creates an independent copy of a stack trace. Required when storing
|
|
// stacks in long-lived structures (e.g. l.order) because the originals are backed
|
|
// by pooled buffers that will be recycled in postUnlock.
|
|
func copyStack(s []uintptr) []uintptr {
|
|
c := make([]uintptr, len(s))
|
|
copy(c, s)
|
|
return c
|
|
}
|
|
|
|
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))
|
|
}
|
|
}
|