diff options
Diffstat (limited to 'internal/probemanager')
| -rw-r--r-- | internal/probemanager/manager.go | 38 | ||||
| -rw-r--r-- | internal/probemanager/manager_test.go | 31 |
2 files changed, 60 insertions, 9 deletions
diff --git a/internal/probemanager/manager.go b/internal/probemanager/manager.go index 5a7e85d..65dd52b 100644 --- a/internal/probemanager/manager.go +++ b/internal/probemanager/manager.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "sort" + "strings" "sync" ) @@ -179,25 +180,44 @@ func (m *Manager) Detach(syscall string) error { } enterLink := entry.enterLink exitLink := entry.exitLink - entry.enterLink = nil - entry.exitLink = nil - entry.active = false m.mu.Unlock() + var errs []string + enterErr := error(nil) if enterLink != nil { if err := enterLink.Destroy(); err != nil { - m.setLastError(syscall, fmt.Errorf("detach enter %s: %w", syscall, err)) - return err + enterErr = err + errs = append(errs, fmt.Sprintf("detach enter %s: %v", syscall, err)) } } + exitErr := error(nil) if exitLink != nil { if err := exitLink.Destroy(); err != nil { - m.setLastError(syscall, fmt.Errorf("detach exit %s: %w", syscall, err)) - return err + exitErr = err + errs = append(errs, fmt.Sprintf("detach exit %s: %v", syscall, err)) } } - m.setLastError(syscall, nil) - return nil + + m.mu.Lock() + defer m.mu.Unlock() + entry, err = m.entryLocked(syscall) + if err != nil { + return err + } + if enterErr == nil { + entry.enterLink = nil + } + if exitErr == nil { + entry.exitLink = nil + } + entry.active = entry.enterLink != nil || entry.exitLink != nil + if len(errs) == 0 { + entry.lastErr = nil + return nil + } + combined := errors.New(strings.Join(errs, "; ")) + entry.lastErr = combined + return combined } func (m *Manager) States() []ProbeState { diff --git a/internal/probemanager/manager_test.go b/internal/probemanager/manager_test.go index f610ea3..1fcce6d 100644 --- a/internal/probemanager/manager_test.go +++ b/internal/probemanager/manager_test.go @@ -114,6 +114,37 @@ func TestManagerDetachDestroysLinks(t *testing.T) { } } +func TestManagerDetachFailureKeepsActiveStateForUndetachedLink(t *testing.T) { + enter := &fakeLink{err: errors.New("destroy failed")} + exit := &fakeLink{} + attacher := &fakeAttacher{ + programs: map[string]*fakeProgram{ + "handle_sys_enter_close": {link: enter}, + "handle_sys_exit_close": {link: exit}, + }, + errs: map[string]error{}, + } + mgr := NewManager(attacher) + if err := mgr.AttachAll(nil, []string{"sys_enter_close", "sys_exit_close"}); err != nil { + t.Fatalf("AttachAll returned error: %v", err) + } + + err := mgr.Detach("close") + if err == nil { + t.Fatalf("expected detach error") + } + states := mgr.States() + if len(states) != 1 { + t.Fatalf("expected one state, got %+v", states) + } + if !states[0].Active { + t.Fatalf("expected probe to remain active when one link failed to detach") + } + if states[0].Error == "" { + t.Fatalf("expected error to be recorded after detach failure") + } +} + func TestManagerClosePreventsFurtherOperations(t *testing.T) { attacher := &fakeAttacher{ programs: map[string]*fakeProgram{ |
