-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathoptions.go
80 lines (71 loc) · 2.26 KB
/
options.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package deadlock
import (
"bufio"
"io"
"os"
"sync"
"sync/atomic"
"time"
)
type Options struct {
// Waiting for a lock for longer than a non-zero DeadlockTimeout milliseconds is considered a deadlock.
// Set to 30 seconds by default.
DeadlockTimeout time.Duration
// OnPotentialDeadlock is called each time a potential deadlock is detected -- either based on
// lock order or on lock wait time. If nil, panics instead.
OnPotentialDeadlock func()
// Sets the maximum size of the map that tracks lock ordering.
// Setting this to zero disables tracking of lock order. Default is a reasonable size.
MaxMapSize int
// Will dump stacktraces of all goroutines when inconsistent locking is detected.
PrintAllCurrentGoroutines bool
// Where to write reports, set to os.Stderr by default.
LogBuf io.Writer
}
var optsLock sync.RWMutex
var maxMapSize int32 = 1024 * 64
var deadlockTimeout int32 = 30 * 1000
// Opts control how deadlock detection behaves.
// To safely read or change options during runtime, use Opts.ReadLocked() and Opts.WriteLocked()
var Opts = Options{
DeadlockTimeout: time.Millisecond * time.Duration(deadlockTimeout),
MaxMapSize: int(maxMapSize),
LogBuf: os.Stderr,
}
// WriteLocked calls the given function with Opts locked for writing.
func (opts *Options) WriteLocked(fn func()) {
optsLock.Lock()
defer optsLock.Unlock()
fn()
atomic.StoreInt32(&maxMapSize, int32(opts.MaxMapSize))
atomic.StoreInt32(&deadlockTimeout, int32(opts.DeadlockTimeout.Nanoseconds()/int64(time.Millisecond)))
}
// ReadLocked calls the given function with Opts locked for reading.
func (opts *Options) ReadLocked(fn func()) {
optsLock.RLock()
defer optsLock.RUnlock()
fn()
}
// Write implements io.Writer for Options.
func (opts *Options) Write(b []byte) (int, error) {
if opts.LogBuf != nil {
return opts.LogBuf.Write(b)
}
return 0, nil
}
// Flush will flush the LogBuf if it is a *bufio.Writer
func (opts *Options) Flush() error {
if opts.LogBuf != nil {
if buf, ok := opts.LogBuf.(*bufio.Writer); ok {
return buf.Flush()
}
}
return nil
}
// PotentialDeadlock calls OnPotentialDeadlock if it is set, or panics if not.
func (opts *Options) PotentialDeadlock() {
if opts.OnPotentialDeadlock == nil {
panic("deadlock detected")
}
opts.OnPotentialDeadlock()
}