From 6f54066c43172fe0197e82fb1034c9ae55d1e1f2 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sat, 27 Apr 2019 15:02:52 +0300 Subject: [PATCH] Add partial deadlock detection in debug mode --- debug/debug.go | 59 +++++++++++++++++++++++++++++++++++--------- go.mod | 2 ++ go.sum | 4 +++ main.go | 17 ++++++++++--- matrix/history.go | 6 ++--- matrix/rooms/room.go | 5 ++-- ui/message-view.go | 2 +- ui/room-list.go | 4 ++- ui/view-main.go | 3 ++- 9 files changed, 79 insertions(+), 23 deletions(-) diff --git a/debug/debug.go b/debug/debug.go index 573cff7..741bb7a 100644 --- a/debug/debug.go +++ b/debug/debug.go @@ -22,40 +22,75 @@ import ( "io" "io/ioutil" "os" + "path/filepath" "runtime/debug" "time" + + "github.com/sasha-s/go-deadlock" ) var writer io.Writer var RecoverPrettyPanic bool +var DeadlockDetection bool +var WriteLogs bool var OnRecover func() +var LogDirectory = filepath.Join(os.TempDir(), "gomuks") -func init() { - var err error - writer, err = os.OpenFile("/tmp/gomuks-debug.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) +func Initialize() { + err := os.MkdirAll(LogDirectory, 0750) if err != nil { - writer = nil + RecoverPrettyPanic = false + DeadlockDetection = false + WriteLogs = false + return + } + + if WriteLogs { + writer, err = os.OpenFile(filepath.Join(LogDirectory, "debug.log"), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640) + if err != nil { + panic(err) + } + } + + _, _ = fmt.Fprintf(writer, "======================= Debug init @ %s =======================\n", time.Now().Format("2006-01-02 15:04:05")) + if DeadlockDetection { + deadlocks, err := os.OpenFile(filepath.Join(LogDirectory, "deadlock.log"), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640) + if err != nil { + panic(err) + } + deadlock.Opts.LogBuf = deadlocks + deadlock.Opts.OnPotentialDeadlock = func() { + if OnRecover != nil { + OnRecover() + } + os.Exit(88) + } + _, err = fmt.Fprintf(deadlocks, "======================= Debug init @ %s =======================\n", time.Now().Format("2006-01-02 15:04:05")) + if err != nil { + panic(err) + } + } else { + deadlock.Opts.Disable = true } } func Printf(text string, args ...interface{}) { if writer != nil { - fmt.Fprintf(writer, time.Now().Format("[2006-01-02 15:04:05] ")) - fmt.Fprintf(writer, text+"\n", args...) + _, _ = fmt.Fprintf(writer, time.Now().Format("[2006-01-02 15:04:05] ")) + _, _ = fmt.Fprintf(writer, text+"\n", args...) } } func Print(text ...interface{}) { if writer != nil { - fmt.Fprintf(writer, time.Now().Format("[2006-01-02 15:04:05] ")) - fmt.Fprintln(writer, text...) + _, _ = fmt.Fprintf(writer, time.Now().Format("[2006-01-02 15:04:05] ")) + _, _ = fmt.Fprintln(writer, text...) } } func PrintStack() { if writer != nil { - data := debug.Stack() - writer.Write(data) + _, _ = writer.Write(debug.Stack()) } } @@ -90,10 +125,10 @@ A fatal error has occurred. func PrettyPanic(panic interface{}) { fmt.Print(Oops) - traceFile := fmt.Sprintf("/tmp/gomuks-panic-%s.txt", time.Now().Format("2006-01-02--15-04-05")) + traceFile := fmt.Sprintf(filepath.Join(LogDirectory, "panic-%s.txt"), time.Now().Format("2006-01-02--15-04-05")) var buf bytes.Buffer - fmt.Fprintln(&buf, panic) + _, _ = fmt.Fprintln(&buf, panic) buf.Write(debug.Stack()) err := ioutil.WriteFile(traceFile, buf.Bytes(), 0640) diff --git a/go.mod b/go.mod index 0437fe2..cc32152 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,9 @@ require ( github.com/mattn/go-isatty v0.0.7 // indirect github.com/mattn/go-runewidth v0.0.4 github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect + github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/russross/blackfriday/v2 v2.0.1 + github.com/sasha-s/go-deadlock v0.2.0 github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/stretchr/objx v0.2.0 // indirect go.etcd.io/bbolt v1.3.2 diff --git a/go.sum b/go.sum index a0d3853..7806d1c 100644 --- a/go.sum +++ b/go.sum @@ -35,12 +35,16 @@ github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/ github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.0.0-20190313204849-f699dde9c340 h1:nOZbL5f2xmBAHWYrrHbHV1xatzZirN++oOQ3g83Ypgs= github.com/rivo/uniseg v0.0.0-20190313204849-f699dde9c340/go.mod h1:SOLvOL4ybwgLJ6TYoX/rtaJ8EGOulH4XU7E9/TLrTCE= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y= +github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= diff --git a/main.go b/main.go index e925f3e..43f4d2b 100644 --- a/main.go +++ b/main.go @@ -22,6 +22,7 @@ import ( "os" "path/filepath" "runtime" + "strings" "time" "maunium.net/go/gomuks/debug" @@ -32,11 +33,21 @@ import ( var MainUIProvider ifc.UIProvider = ui.NewGomuksUI func main() { + debugDir := os.Getenv("DEBUG_DIR") + if len(debugDir) > 0 { + debug.LogDirectory = debugDir + } + debugLevel := strings.ToLower(os.Getenv("DEBUG")) + if debugLevel != "0" && debugLevel != "f" && debugLevel != "false" { + debug.WriteLogs = true + } + if debugLevel == "1" || debugLevel == "t" || debugLevel == "true" { + debug.RecoverPrettyPanic = false + debug.DeadlockDetection = true + } + debug.Initialize() defer debug.Recover() - enableDebug := len(os.Getenv("DEBUG")) > 0 - debug.RecoverPrettyPanic = !enableDebug - configDir, err := UserConfigDir() if err != nil { fmt.Fprintln(os.Stderr, "Failed to get config directory:", err) diff --git a/matrix/history.go b/matrix/history.go index 0cfb84e..767cace 100644 --- a/matrix/history.go +++ b/matrix/history.go @@ -20,8 +20,8 @@ import ( "bytes" "encoding/binary" "encoding/gob" - "sync" + sync "github.com/sasha-s/go-deadlock" bolt "go.etcd.io/bbolt" "maunium.net/go/gomuks/matrix/rooms" @@ -49,8 +49,8 @@ func NewHistoryManager(dbPath string) (*HistoryManager, error) { historyLoadPtr: make(map[*rooms.Room]uint64), } db, err := bolt.Open(dbPath, 0600, &bolt.Options{ - Timeout: 1, - NoGrowSync: false, + Timeout: 1, + NoGrowSync: false, FreelistType: bolt.FreelistArrayType, }) if err != nil { diff --git a/matrix/rooms/room.go b/matrix/rooms/room.go index 6334036..717636b 100644 --- a/matrix/rooms/room.go +++ b/matrix/rooms/room.go @@ -21,9 +21,10 @@ import ( "fmt" "os" "sort" - "sync" "time" + sync "github.com/sasha-s/go-deadlock" + "maunium.net/go/mautrix" "maunium.net/go/gomuks/debug" @@ -450,7 +451,7 @@ func (room *Room) GetSessionOwner() string { // NewRoom creates a new Room with the given ID func NewRoom(roomID, owner string) *Room { return &Room{ - Room: mautrix.NewRoom(roomID), + Room: mautrix.NewRoom(roomID), SessionUserID: owner, } } diff --git a/ui/message-view.go b/ui/message-view.go index 43c757f..75cd022 100644 --- a/ui/message-view.go +++ b/ui/message-view.go @@ -20,10 +20,10 @@ import ( "fmt" "math" "strings" - "sync" "sync/atomic" "github.com/mattn/go-runewidth" + sync "github.com/sasha-s/go-deadlock" "maunium.net/go/mauview" "maunium.net/go/tcell" diff --git a/ui/room-list.go b/ui/room-list.go index 47ac182..0dc3e74 100644 --- a/ui/room-list.go +++ b/ui/room-list.go @@ -20,7 +20,8 @@ import ( "math" "regexp" "strings" - "sync" + + sync "github.com/sasha-s/go-deadlock" "maunium.net/go/mauview" "maunium.net/go/tcell" @@ -483,6 +484,7 @@ func (list *RoomList) clickRoom(line, column int, mod bool) bool { } return false } + var nsRegex = regexp.MustCompile("^[a-z]\\.[a-z](?:\\.[a-z])*$") func (list *RoomList) GetTagDisplayName(tag string) string { diff --git a/ui/view-main.go b/ui/view-main.go index 2d2afdf..48004c1 100644 --- a/ui/view-main.go +++ b/ui/view-main.go @@ -20,11 +20,12 @@ import ( "bufio" "fmt" "os" - "sync" "sync/atomic" "time" "unicode" + sync "github.com/sasha-s/go-deadlock" + "maunium.net/go/mauview" "maunium.net/go/tcell"