Skip to content

feat(tracepoint): add sched_process_exec tracepoint#2154

Open
sparkzky wants to merge 6 commits into
DragonOS-Community:masterfrom
sparkzky:feature/sched-process-exec-tracepoint
Open

feat(tracepoint): add sched_process_exec tracepoint#2154
sparkzky wants to merge 6 commits into
DragonOS-Community:masterfrom
sparkzky:feature/sched-process-exec-tracepoint

Conversation

@sparkzky

Copy link
Copy Markdown
Member

为 execve 成功路径添加 sched_process_exec tracepoint,供 ANOLISA agentsight 的 eBPF 程序追踪进程 exec 事件、构建 AI agent 进程树。

变更内容

  • 新增 kernel/src/process/trace.rs:声明 sched_process_exec tracepoint(comm/pid/old_pid 字段),TP_system(sched)。字段参考 Linux include/trace/events/sched.h
  • kernel/src/process/execve.rs:在 load_binary_file_with_context 之前捕获 old_pidde_thread 会交换 pid);trace 调用置于 arch_do_execve 成功后、is_ok() 分支内,对齐 Linux fs/exec.c exec_binprm()trace_sched_process_exec 的调用位置。
  • kernel/src/process/mod.rs:注册 process::trace 模块。

设计说明

  • DragonOS 的 define_event_trace! 宏不支持 Linux 的 __string 动态字符串,且当前未实现 bpf_get_current_comm() helper,故 comm 直接放入 payload([u8; 16],对齐 TASK_COMM_LEN)。
  • TP_printk 在首个 NUL 字节处截断 comm,使用 Display 格式输出,输出格式对齐 Linux 的 comm=... pid=... old_pid=...
  • tracepoint 注册、debugfs 导出、eBPF attach 全部由现有框架自动完成。static key 保证未启用时零开销。

Refs: #2149

为 execve 成功路径添加 sched_process_exec tracepoint,供 ANOLISA agentsight 的 eBPF 程序追踪进程 exec 事件、构建 AI agent 进程树。

- 新增 kernel/src/process/trace.rs:声明 sched_process_exec tracepoint(comm/pid/old_pid 字段),TP_system(sched)
- execve.rs:在 load_binary_file_with_context 之前捕获 old_pid(de_thread 会交换 pid);trace 调用置于 arch_do_execve 成功后、is_ok() 分支内,对齐 Linux fs/exec.c:1803
- mod.rs:注册 process::trace 模块

tracepoint 注册、debugfs 导出、eBPF attach 全部由现有框架自动完成。static key 保证未启用时零开销。

Refs: DragonOS-Community#2149
Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
@github-actions github-actions Bot added the enhancement New feature or request label Jul 22, 2026
新增 sched_tracepoint dunitest,验证 sched_process_exec tracepoint 的 debugfs 导出(format/enable/id 文件 + 字段)与 execve 触发行为。

- EventFilesExist: 验证 events/sched/sched_process_exec/{format,id,enable} 存在,format 含 comm/pid/old_pid/common_pid 字段
- FiresOnExecve: enable + 清空 trace 后 fork+execve(/proc/self/exe),断言 trace 含 sched_process_exec 记录与 comm 字段
- whitelist 注册 normal/sched_tracepoint

Refs: DragonOS-Community#2149
Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
@fslongjin

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5b1c50988b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

TP_system(sched),
TP_PROTO(comm: &str, pid: i32, old_pid: i32),
TP_STRUCT__entry {
comm: [u8; 16],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 保持 sched_process_exec 的 filename ABI

这里把事件 payload 定义成 comm 会让 /tracing/events/sched/sched_process_exec/format 暴露为 comm,pid,old_pid,而 Linux 6.6 的同名 tracepoint ABI 是 filename,pid,old_pidfilename 还是第一项,见 https://codebrowser.dev/linux/linux/include/trace/events/sched.h.html#431)。因此按 Linux format 编译或按 filename 过滤/解析的 eBPF/trace 工具会在 DragonOS 上找不到字段,raw offset 也会读错,恰好破坏本次为 agentsight 兼容该 tracepoint 的目的;即使暂时不能实现动态 __string,也应保留 filename 字段语义/名称并从 exec 参数填充。

Useful? React with 👍 / 👎.

Comment thread kernel/src/process/execve.rs Outdated
// sched_process_exec:arch_do_execve 成功、用户态寄存器就绪后触发,
// 对齐 Linux fs/exec.c:1803(trace 在 start_thread 之后、所有失败点之后)。
let pid = pcb.raw_pid().data() as i32;
trace_sched_process_exec(pcb.basic().name(), pid, old_pid);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 先释放 basic 读锁再触发 tracepoint

sched_process_exec 已启用且另一个 CPU 已在这个进程的 basic 锁上排队写锁时,pcb.basic().name() 产生的读锁 guard 会一直持有到 trace_sched_process_exec 返回;但默认 tracepoint callback 会在 kernel/src/tracepoint/basic_macro.rs 中调用 trace_cmdline_push(),它又对当前进程执行 process.basic() 读锁获取。DragonOS 的 RwLock 在有 pending writer 时会阻止新读者,所以当前 CPU 会等待 writer,而 writer 又等外层读锁释放,导致 exec 路径自旋卡死;应先把名称复制到局部并让 guard drop,或避免 trace 路径重入读取同一把锁。

Useful? React with 👍 / 👎.

sparkzky added 3 commits July 23, 2026 01:55
TracePointIdFile 的 id 由 global_init_events 的 AtomicUsize::new(0) fetch_add 分配,从 0 开始递增。原断言 EXPECT_GT(idval, 0) 错误假设 id 从 1 开始,导致 CI 中拿到 id=0 的 tracepoint 失败。改为 EXPECT_GE(idval, 0)。

Refs: DragonOS-Community#2149
Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
…exec

PR review 发现:trace_sched_process_exec(pcb.basic().name(), ...) 持有 basic 读锁 guard 直到 trace 调用返回,而 trace 默认回调内部的 trace_cmdline_push() 会再次获取同一把 basic 读锁。DragonOS RwLock 读锁不可重入,若此时另一 CPU 排队写锁,将导致 reader 等 writer、writer 等 reader 的 deadlock。

修复:先将 comm 复制到栈缓冲并在内层作用域释放读锁 guard,再调用 trace,消除锁重入。

Refs: DragonOS-Community#2149
Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
bug-hunter fanout 发现:comm_len = bytes.len().min(15) 在原始字节偏移截断,当进程名第 15 字节落在多字节 UTF-8 字符中间时(如 Unicode 路径名),from_utf8 失败导致 comm 变空字符串。用 is_char_boundary 回退到字符边界修复。

同时加强测试:strtol 解析 id 后校验 end 指针,确认整个字符串都是数字而非仅前缀可解析。

Refs: DragonOS-Community#2149
Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
@sparkzky

Copy link
Copy Markdown
Member Author

感谢这两条 review,已逐条处理:

① trace.rs:14 — 保持 filename ABI(不采纳)

经 bug-hunter 多角色 fanout 审查(ABI 维度)独立确认:comm 替代 filename 是当前能力下的有意设计决策,而非疏忽。原因有二:

  • define_event_trace! 宏不支持 __string 动态字符串(字段类型固定 ty),无法表达 Linux 的变长 filename
  • DragonOS 未实现 bpf_get_current_comm() helper,eBPF 读进程名只能走 tracepoint 载荷。

因此「保留 filename 字段名」的折中在技术上无意义——offset 兼容性依赖 __string 的动态布局,仅改字段名解决不了 raw offset 读取,反而让 basename 被当成完整路径语义更混乱。当前 comm(basename,对齐 TASK_COMM_LEN=16)方案与 DragonOS 既有 tracepoint 风格一致(如 do_mkdir_at 同样把路径放载荷)。agentsight 完整闭环需要的 helper 能力属独立工作(见方案文档「非目标」节)。

② execve.rs:226 — 先释放 basic 读锁再触发 tracepoint(采纳,已修复)

确认是真问题。pcb.basic().name() 的读锁 guard 作为临时值,生命周期延长到整个 trace_sched_process_exec(...) 调用结束;而 trace 默认回调内部的 trace_cmdline_push() 会再次 process.basic() 获取同一把 RwLock 读锁。DragonOS RwLock 读锁不可重入,若此时另一 CPU 排队写锁,将导致 reader 等 writer、writer 等 reader 的 deadlock。

修复(commit 72222fff):先将 comm 复制到栈缓冲 [u8;16],在内层作用域显式 drop 读锁 guard,再调用 trace,消除锁重入。bug-hunter Concurrency 维度复核确认修复彻底(「trace call site releases both guards before invoking trace; copy-to-stack correctly avoids RwLock re-entry」)。

附带:fanout 的 EdgeCases 维度还发现我修锁时引入的一个回归——comm 截断在原始字节偏移,多字节 UTF-8 路径名(如 12345678901234π)会在第 15 字节拆分字符导致 from_utf8 失败、comm 变空。已用 is_char_boundary 回退到字符边界修复(commit a9e1305a)。

make fmt / clippy: name.as_bytes().len() → name.len()(字符串可直接调 len())。

Refs: DragonOS-Community#2149
Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants