forked from Velocidex/velociraptor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprogress.go
90 lines (77 loc) · 1.74 KB
/
progress.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
81
82
83
84
85
86
87
88
89
90
package actions
import (
"bytes"
"context"
"runtime/pprof"
"sync"
"time"
"www.velocidex.com/golang/vfilter"
"www.velocidex.com/golang/vfilter/types"
)
type ProgressThrottler struct {
mu sync.Mutex
delegate types.Throttler
progress_timeout time.Duration
heartbeat time.Time
// Will be called when an alarm is fired.
cancel func()
}
func (self *ProgressThrottler) ChargeOp() {
self.mu.Lock()
self.heartbeat = time.Now()
self.mu.Unlock()
self.delegate.ChargeOp()
}
func (self *ProgressThrottler) Close() {
self.delegate.Close()
}
func (self *ProgressThrottler) Start(
ctx context.Context, scope vfilter.Scope) {
for {
select {
case <-ctx.Done():
return
case <-time.After(self.progress_timeout):
self.mu.Lock()
now := time.Now()
if self.progress_timeout.Nanoseconds() > 0 &&
now.After(self.heartbeat.Add(self.progress_timeout)) {
self.mu.Unlock()
self.exitWithError(scope)
return
}
self.mu.Unlock()
}
}
}
func (self *ProgressThrottler) exitWithError(scope vfilter.Scope) {
buf := bytes.Buffer{}
p := pprof.Lookup("goroutine")
if p != nil {
p.WriteTo(&buf, 1)
scope.Log("Goroutine dump: %v", buf.String())
}
buf = bytes.Buffer{}
p = pprof.Lookup("mutex")
if p != nil {
p.WriteTo(&buf, 1)
scope.Log("Mutex dump: %v", buf.String())
}
for _, q := range QueryLog.Get() {
scope.Log("Recent Query: %v", q)
}
self.cancel()
}
func NewProgressThrottler(
ctx context.Context, scope vfilter.Scope,
cancel func(),
throttler types.Throttler,
progress_timeout time.Duration) types.Throttler {
result := &ProgressThrottler{
cancel: cancel,
delegate: throttler,
progress_timeout: progress_timeout,
}
go result.Start(ctx, scope)
return result
}