Add partial deadlock detection in debug mode

This commit is contained in:
Tulir Asokan 2019-04-27 15:02:52 +03:00
parent bc7e2d9a1c
commit 6f54066c43
9 changed files with 79 additions and 23 deletions

View File

@ -22,40 +22,75 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath"
"runtime/debug" "runtime/debug"
"time" "time"
"github.com/sasha-s/go-deadlock"
) )
var writer io.Writer var writer io.Writer
var RecoverPrettyPanic bool var RecoverPrettyPanic bool
var DeadlockDetection bool
var WriteLogs bool
var OnRecover func() var OnRecover func()
var LogDirectory = filepath.Join(os.TempDir(), "gomuks")
func init() { func Initialize() {
var err error err := os.MkdirAll(LogDirectory, 0750)
writer, err = os.OpenFile("/tmp/gomuks-debug.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
if err != nil { 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{}) { func Printf(text string, args ...interface{}) {
if writer != nil { if writer != nil {
fmt.Fprintf(writer, time.Now().Format("[2006-01-02 15:04:05] ")) _, _ = fmt.Fprintf(writer, time.Now().Format("[2006-01-02 15:04:05] "))
fmt.Fprintf(writer, text+"\n", args...) _, _ = fmt.Fprintf(writer, text+"\n", args...)
} }
} }
func Print(text ...interface{}) { func Print(text ...interface{}) {
if writer != nil { if writer != nil {
fmt.Fprintf(writer, time.Now().Format("[2006-01-02 15:04:05] ")) _, _ = fmt.Fprintf(writer, time.Now().Format("[2006-01-02 15:04:05] "))
fmt.Fprintln(writer, text...) _, _ = fmt.Fprintln(writer, text...)
} }
} }
func PrintStack() { func PrintStack() {
if writer != nil { if writer != nil {
data := debug.Stack() _, _ = writer.Write(debug.Stack())
writer.Write(data)
} }
} }
@ -90,10 +125,10 @@ A fatal error has occurred.
func PrettyPanic(panic interface{}) { func PrettyPanic(panic interface{}) {
fmt.Print(Oops) 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 var buf bytes.Buffer
fmt.Fprintln(&buf, panic) _, _ = fmt.Fprintln(&buf, panic)
buf.Write(debug.Stack()) buf.Write(debug.Stack())
err := ioutil.WriteFile(traceFile, buf.Bytes(), 0640) err := ioutil.WriteFile(traceFile, buf.Bytes(), 0640)

2
go.mod
View File

@ -14,7 +14,9 @@ require (
github.com/mattn/go-isatty v0.0.7 // indirect github.com/mattn/go-isatty v0.0.7 // indirect
github.com/mattn/go-runewidth v0.0.4 github.com/mattn/go-runewidth v0.0.4
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect 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/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/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/stretchr/objx v0.2.0 // indirect github.com/stretchr/objx v0.2.0 // indirect
go.etcd.io/bbolt v1.3.2 go.etcd.io/bbolt v1.3.2

4
go.sum
View File

@ -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/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 h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= 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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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 h1:nOZbL5f2xmBAHWYrrHbHV1xatzZirN++oOQ3g83Ypgs=
github.com/rivo/uniseg v0.0.0-20190313204849-f699dde9c340/go.mod h1:SOLvOL4ybwgLJ6TYoX/rtaJ8EGOulH4XU7E9/TLrTCE= 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 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 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/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 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=

17
main.go
View File

@ -22,6 +22,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings"
"time" "time"
"maunium.net/go/gomuks/debug" "maunium.net/go/gomuks/debug"
@ -32,11 +33,21 @@ import (
var MainUIProvider ifc.UIProvider = ui.NewGomuksUI var MainUIProvider ifc.UIProvider = ui.NewGomuksUI
func main() { 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() defer debug.Recover()
enableDebug := len(os.Getenv("DEBUG")) > 0
debug.RecoverPrettyPanic = !enableDebug
configDir, err := UserConfigDir() configDir, err := UserConfigDir()
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "Failed to get config directory:", err) fmt.Fprintln(os.Stderr, "Failed to get config directory:", err)

View File

@ -20,8 +20,8 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"encoding/gob" "encoding/gob"
"sync"
sync "github.com/sasha-s/go-deadlock"
bolt "go.etcd.io/bbolt" bolt "go.etcd.io/bbolt"
"maunium.net/go/gomuks/matrix/rooms" "maunium.net/go/gomuks/matrix/rooms"
@ -49,8 +49,8 @@ func NewHistoryManager(dbPath string) (*HistoryManager, error) {
historyLoadPtr: make(map[*rooms.Room]uint64), historyLoadPtr: make(map[*rooms.Room]uint64),
} }
db, err := bolt.Open(dbPath, 0600, &bolt.Options{ db, err := bolt.Open(dbPath, 0600, &bolt.Options{
Timeout: 1, Timeout: 1,
NoGrowSync: false, NoGrowSync: false,
FreelistType: bolt.FreelistArrayType, FreelistType: bolt.FreelistArrayType,
}) })
if err != nil { if err != nil {

View File

@ -21,9 +21,10 @@ import (
"fmt" "fmt"
"os" "os"
"sort" "sort"
"sync"
"time" "time"
sync "github.com/sasha-s/go-deadlock"
"maunium.net/go/mautrix" "maunium.net/go/mautrix"
"maunium.net/go/gomuks/debug" "maunium.net/go/gomuks/debug"
@ -450,7 +451,7 @@ func (room *Room) GetSessionOwner() string {
// NewRoom creates a new Room with the given ID // NewRoom creates a new Room with the given ID
func NewRoom(roomID, owner string) *Room { func NewRoom(roomID, owner string) *Room {
return &Room{ return &Room{
Room: mautrix.NewRoom(roomID), Room: mautrix.NewRoom(roomID),
SessionUserID: owner, SessionUserID: owner,
} }
} }

View File

@ -20,10 +20,10 @@ import (
"fmt" "fmt"
"math" "math"
"strings" "strings"
"sync"
"sync/atomic" "sync/atomic"
"github.com/mattn/go-runewidth" "github.com/mattn/go-runewidth"
sync "github.com/sasha-s/go-deadlock"
"maunium.net/go/mauview" "maunium.net/go/mauview"
"maunium.net/go/tcell" "maunium.net/go/tcell"

View File

@ -20,7 +20,8 @@ import (
"math" "math"
"regexp" "regexp"
"strings" "strings"
"sync"
sync "github.com/sasha-s/go-deadlock"
"maunium.net/go/mauview" "maunium.net/go/mauview"
"maunium.net/go/tcell" "maunium.net/go/tcell"
@ -483,6 +484,7 @@ func (list *RoomList) clickRoom(line, column int, mod bool) bool {
} }
return false return false
} }
var nsRegex = regexp.MustCompile("^[a-z]\\.[a-z](?:\\.[a-z])*$") var nsRegex = regexp.MustCompile("^[a-z]\\.[a-z](?:\\.[a-z])*$")
func (list *RoomList) GetTagDisplayName(tag string) string { func (list *RoomList) GetTagDisplayName(tag string) string {

View File

@ -20,11 +20,12 @@ import (
"bufio" "bufio"
"fmt" "fmt"
"os" "os"
"sync"
"sync/atomic" "sync/atomic"
"time" "time"
"unicode" "unicode"
sync "github.com/sasha-s/go-deadlock"
"maunium.net/go/mauview" "maunium.net/go/mauview"
"maunium.net/go/tcell" "maunium.net/go/tcell"