Skip to content

Commit

Permalink
fix: escape deathlock in agent
Browse files Browse the repository at this point in the history
  • Loading branch information
siyul-park committed Sep 28, 2024
1 parent da54499 commit 71d9d4e
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 19 deletions.
25 changes: 17 additions & 8 deletions pkg/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ type Agent struct {
mu sync.RWMutex
}

// Ensure Agent implements LoadHook and UnloadHook interfaces.
var _ symbol.LoadHook = (*Agent)(nil)
var _ symbol.UnloadHook = (*Agent)(nil)

Expand Down Expand Up @@ -117,7 +116,7 @@ func (a *Agent) Frames(id uuid.UUID) ([]*Frame, bool) {
if !exists {
return nil, false
}
return append([]*Frame(nil), frames...), true
return frames[:], true
}

// Load adds a symbol and its hooks to the agent.
Expand Down Expand Up @@ -202,9 +201,10 @@ func (a *Agent) Close() {
// accept registers a process and notifies watchers.
func (a *Agent) accept(proc *process.Process) {
a.mu.Lock()
defer a.mu.Unlock()

if _, exists := a.processes[proc.ID()]; !exists {
_, exists := a.processes[proc.ID()]

if !exists {
a.processes[proc.ID()] = proc

proc.AddExitHook(process.ExitFunc(func(err error) {
Expand All @@ -215,14 +215,21 @@ func (a *Agent) accept(proc *process.Process) {
delete(a.frames, proc.ID())
}))

for _, watcher := range a.watchers {
watcher.OnProcess(proc)
}

if _, exists := a.frames[proc.ID()]; !exists {
a.frames[proc.ID()] = nil
}
}

watchers := a.watchers[:]

a.mu.Unlock()

if !exists {
for i := len(watchers) - 1; i >= 0; i-- {
watcher := watchers[i]
watcher.OnProcess(proc)
}
}
}

func (a *Agent) hooks(proc *process.Process, sym *symbol.Symbol, in *port.InPort, out *port.OutPort) (packet.Hook, packet.Hook) {
Expand Down Expand Up @@ -251,6 +258,7 @@ func (a *Agent) hooks(proc *process.Process, sym *symbol.Symbol, in *port.InPort
}

watchers := a.watchers[:]

a.mu.Unlock()

for i := len(watchers) - 1; i >= 0; i-- {
Expand Down Expand Up @@ -284,6 +292,7 @@ func (a *Agent) hooks(proc *process.Process, sym *symbol.Symbol, in *port.InPort
}

watchers := a.watchers[:]

a.mu.Unlock()

for i := len(watchers) - 1; i >= 0; i-- {
Expand Down
13 changes: 5 additions & 8 deletions pkg/debug/debugger.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,13 @@ func (d *Debugger) Breakpoints() []*Breakpoint {
d.mu.RLock()
defer d.mu.RUnlock()

if len(d.breakpoints) == 0 {
return nil
}
return append([]*Breakpoint(nil), d.breakpoints...)
return d.breakpoints[:]
}

// Pause blocks until a breakpoint is hit or monitoring is done.
func (d *Debugger) Pause(ctx context.Context) bool {
d.mu.RLock()
defer d.mu.RUnlock()
d.mu.Lock()
defer d.mu.Unlock()

if d.current != nil {
return true
Expand All @@ -95,8 +92,8 @@ func (d *Debugger) Pause(ctx context.Context) bool {

// Step continues execution until the next breakpoint is hit.
func (d *Debugger) Step(ctx context.Context) bool {
d.mu.RLock()
defer d.mu.RUnlock()
d.mu.Lock()
defer d.mu.Unlock()

if d.current != nil {
go d.next(d.current)
Expand Down
6 changes: 3 additions & 3 deletions pkg/process/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,23 +50,23 @@ func (p *Process) ID() uuid.UUID {
func (p *Process) Load(key string) any {
p.mu.RLock()
defer p.mu.RUnlock()

return p.data[key]
}

// Store stores the value under the given key.
func (p *Process) Store(key string, val any) {
p.mu.Lock()
defer p.mu.Unlock()

p.data[key] = val
}

// Delete removes the value for the given key.
func (p *Process) Delete(key string) bool {
p.mu.Lock()
defer p.mu.Unlock()

if _, ok := p.data[key]; ok {
delete(p.data, key)
return true
Expand Down

0 comments on commit 71d9d4e

Please sign in to comment.