diff options
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/probemanager/manager.go | 38 | ||||
| -rw-r--r-- | internal/probemanager/manager_test.go | 31 | ||||
| -rw-r--r-- | internal/tui/probes/model.go | 24 |
3 files changed, 83 insertions, 10 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{ diff --git a/internal/tui/probes/model.go b/internal/tui/probes/model.go index 5715d03..dffa30f 100644 --- a/internal/tui/probes/model.go +++ b/internal/tui/probes/model.go @@ -4,6 +4,7 @@ import ( "fmt" "ior/internal/probemanager" "strings" + "unicode/utf8" "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" @@ -266,7 +267,7 @@ func (m Model) View(width, height int) string { } line := fmt.Sprintf("%s%s %-24s", prefix, check, p.Syscall) if p.Error != "" { - line += " ! " + p.Error + line += " ! " + truncateText(sanitizeOneLine(p.Error), 28) } lines = append(lines, line) } @@ -313,3 +314,24 @@ func bulkToggleCmd(manager Manager, probes []probemanager.ProbeState, sourceActi return ProbeToggledMsg{Err: firstErr} } } + +func sanitizeOneLine(s string) string { + s = strings.ReplaceAll(s, "\n", " ") + s = strings.ReplaceAll(s, "\r", " ") + s = strings.ReplaceAll(s, "\t", " ") + return s +} + +func truncateText(s string, limit int) string { + if limit <= 0 { + return "" + } + if utf8.RuneCountInString(s) <= limit { + return s + } + runes := []rune(s) + if limit <= 3 { + return string(runes[:limit]) + } + return string(runes[:limit-3]) + "..." +} |
