Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 24 additions & 24 deletions internal/executor/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,15 @@ var Registry = map[string]*ToolSpec{
Name: "tcpconnlat", Binary: "tcpconnlat", Category: "network",
NeedsRoot: true, OutputType: TABULAR, PIDFlag: "-p",
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) { return ParseTcpconnlat(raw, 1000) },
},
"tcpretrans": {
Name: "tcpretrans", Binary: "tcpretrans", Category: "network",
NeedsRoot: true, OutputType: TABULAR,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) { return ParseTcpretrans(raw, 1000) },
},
Expand All @@ -139,23 +139,23 @@ var Registry = map[string]*ToolSpec{
Name: "gethostlatency", Binary: "gethostlatency", Category: "network",
NeedsRoot: true, OutputType: TABULAR, PIDFlag: "-p",
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) { return ParseGethostlatency(raw, 1000) },
},
"tcpdrop": {
Name: "tcpdrop", Binary: "tcpdrop", Category: "network",
NeedsRoot: true, OutputType: TRACING,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) { return ParseTcpdrop(raw, 1000) },
},
"tcpstates": {
Name: "tcpstates", Binary: "tcpstates", Category: "network",
NeedsRoot: true, OutputType: TABULAR,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
// tcpstates output is complex, treat as tabular for now
Expand Down Expand Up @@ -234,7 +234,7 @@ var Registry = map[string]*ToolSpec{
Name: "killsnoop", Binary: "killsnoop", Category: "process",
NeedsRoot: true, OutputType: TABULAR, PIDFlag: "-p",
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -245,7 +245,7 @@ var Registry = map[string]*ToolSpec{
Name: "threadsnoop", Binary: "threadsnoop", Category: "process",
NeedsRoot: true, OutputType: TABULAR,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -256,7 +256,7 @@ var Registry = map[string]*ToolSpec{
Name: "syncsnoop", Binary: "syncsnoop", Category: "process",
NeedsRoot: true, OutputType: TABULAR,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -267,7 +267,7 @@ var Registry = map[string]*ToolSpec{
Name: "exitsnoop", Binary: "exitsnoop", Category: "process",
NeedsRoot: true, OutputType: TABULAR,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -289,7 +289,7 @@ var Registry = map[string]*ToolSpec{
Name: "capable", Binary: "capable", Category: "process",
NeedsRoot: true, OutputType: TABULAR, PIDFlag: "-p",
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -302,7 +302,7 @@ var Registry = map[string]*ToolSpec{
Name: "filelife", Binary: "filelife", Category: "disk",
NeedsRoot: true, OutputType: TABULAR, PIDFlag: "-p",
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -313,7 +313,7 @@ var Registry = map[string]*ToolSpec{
Name: "mountsnoop", Binary: "mountsnoop", Category: "disk",
NeedsRoot: true, OutputType: TABULAR,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand Down Expand Up @@ -370,7 +370,7 @@ var Registry = map[string]*ToolSpec{
Name: "mdflush", Binary: "mdflush", Category: "disk",
NeedsRoot: true, OutputType: TABULAR,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -394,7 +394,7 @@ var Registry = map[string]*ToolSpec{
Name: "cpufreq", Binary: "cpufreq", Category: "cpu",
NeedsRoot: true, OutputType: TABULAR,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -418,7 +418,7 @@ var Registry = map[string]*ToolSpec{
Name: "tcpconnect", Binary: "tcpconnect", Category: "network",
NeedsRoot: true, OutputType: TABULAR, PIDFlag: "-p",
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -429,7 +429,7 @@ var Registry = map[string]*ToolSpec{
Name: "tcpaccept", Binary: "tcpaccept", Category: "network",
NeedsRoot: true, OutputType: TABULAR, PIDFlag: "-p",
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -440,7 +440,7 @@ var Registry = map[string]*ToolSpec{
Name: "tcplife", Binary: "tcplife", Category: "network",
NeedsRoot: true, OutputType: TABULAR, PIDFlag: "-p",
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -451,7 +451,7 @@ var Registry = map[string]*ToolSpec{
Name: "udpconnect", Binary: "udpconnect", Category: "network",
NeedsRoot: true, OutputType: TABULAR,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -462,7 +462,7 @@ var Registry = map[string]*ToolSpec{
Name: "sofdsnoop", Binary: "sofdsnoop", Category: "network",
NeedsRoot: true, OutputType: TABULAR,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -484,7 +484,7 @@ var Registry = map[string]*ToolSpec{
Name: "skbdrop", Binary: "skbdrop", Category: "network",
NeedsRoot: true, OutputType: TRACING,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -498,7 +498,7 @@ var Registry = map[string]*ToolSpec{
Name: "oomkill", Binary: "oomkill", Category: "memory",
NeedsRoot: true, OutputType: TABULAR,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -509,7 +509,7 @@ var Registry = map[string]*ToolSpec{
Name: "shmsnoop", Binary: "shmsnoop", Category: "memory",
NeedsRoot: true, OutputType: TABULAR,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -520,7 +520,7 @@ var Registry = map[string]*ToolSpec{
Name: "drsnoop", Binary: "drsnoop", Category: "memory",
NeedsRoot: true, OutputType: TABULAR,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand All @@ -533,7 +533,7 @@ var Registry = map[string]*ToolSpec{
Name: "numamove", Binary: "numamove", Category: "memory",
NeedsRoot: true, OutputType: TABULAR,
BuildArgs: func(d time.Duration) []string {
return []string{formatDuration(d)}
return nil // event-based tool — no duration arg, killed by context timeout
},
Parser: func(raw string) (*model.Result, error) {
events, trunc := ParseTabularEvents(raw, 1000)
Expand Down
61 changes: 61 additions & 0 deletions internal/executor/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,3 +303,64 @@ func TestSkbdropParsesStacksAndEvents(t *testing.T) {
t.Error("expected kernel stacks from skbdrop")
}
}

// TestEventBasedToolsNoArgs verifies that event-based BCC tools
// (tcpretrans, tcpdrop, oomkill, tcpstates) do NOT pass duration
// as a positional argument. These tools don't accept duration — they
// run until killed by context timeout. Passing duration causes errors
// like "unrecognized arguments: 10". See issue #19.
func TestEventBasedToolsNoArgs(t *testing.T) {
eventTools := []string{
// Issue #19: these tools don't accept duration as positional arg
"tcpretrans", "tcpdrop", "oomkill", "tcpstates",
// Event tracers — run until killed
"killsnoop", "threadsnoop", "syncsnoop", "exitsnoop",
"capable", "filelife", "mountsnoop", "mdflush", "cpufreq",
"tcpconnect", "tcpaccept", "tcplife", "udpconnect", "sofdsnoop",
"skbdrop", "shmsnoop", "drsnoop", "numamove",
// Positional arg is filter threshold, not duration
"tcpconnlat", // arg = min_ms filter
"gethostlatency", // no positional args
}

for _, name := range eventTools {
t.Run(name, func(t *testing.T) {
tool, ok := Registry[name]
if !ok {
t.Fatalf("tool %q not in registry", name)
}
if tool.BuildArgs == nil {
t.Fatalf("tool %q has nil BuildArgs", name)
}

args := tool.BuildArgs(10 * time.Second)
if len(args) > 0 {
t.Errorf("tool %q BuildArgs(10s) = %v, want nil/empty (event-based tool should not pass duration)",
name, args)
}
})
}
}

// TestDurationToolsHaveArgs verifies that duration-based BCC tools
// DO pass arguments (regression guard for the opposite direction).
func TestDurationToolsHaveArgs(t *testing.T) {
durationTools := []string{"runqlat", "biolatency", "biosnoop", "opensnoop", "hardirqs", "softirqs"}

for _, name := range durationTools {
t.Run(name, func(t *testing.T) {
tool, ok := Registry[name]
if !ok {
t.Skipf("tool %q not in registry", name)
}
if tool.BuildArgs == nil {
t.Fatalf("tool %q has nil BuildArgs", name)
}

args := tool.BuildArgs(10 * time.Second)
if len(args) == 0 {
t.Errorf("tool %q BuildArgs(10s) returned empty args, expected duration arg", name)
}
})
}
}
Loading