@@ -58,12 +58,48 @@ bool write_file(const char* path, const char* data) {
5858 return n == static_cast <ssize_t >(len);
5959}
6060
61- // mount debugfs 到 root。
62- void mount_debugfs (const char * root) {
63- ASSERT_EQ (0 , mount (" none" , root, " debugfs" , 0 , nullptr ))
64- << " mount debugfs failed: errno=" << errno << " (" << strerror (errno) << " )" ;
61+ // mount debugfs 到 root。返回 AssertionResult,供调用处 ASSERT_TRUE 在 mount
62+ // 失败时终止当前 TEST(Thread7:避免 void helper 里的 fatal assertion 只 return helper
63+ // 而让测试继续对着普通目录跑、产生连锁失败)。
64+ ::testing::AssertionResult mount_debugfs (const char * root) {
65+ if (mount (" none" , root, " debugfs" , 0 , nullptr ) != 0 ) {
66+ return ::testing::AssertionFailure ()
67+ << " mount debugfs failed: errno=" << errno << " (" << strerror (errno)
68+ << " )" ;
69+ }
70+ return ::testing::AssertionSuccess ();
6571}
6672
73+ // RAII guard:持有 debugfs mount 点,保证任意 ASSERT 提前 return 时都恢复测试前
74+ // 状态(Thread8:否则中途 ASSERT 失败会泄漏 enabled 的 static key + mount 点,污染
75+ // 共享 buffer 并给后续无关 exec 永久加开销)。
76+ //
77+ // 构造前提:mount_debugfs 已成功(mount 已生效)。此时析构必须 umount + rmdir。
78+ // arm_enable():在事件成功 enable 后调用,记录 enable 文件路径;析构时写回 "0"。
79+ // 析构顺序:disable(仅当 arm 过)→ umount → rmdir。不可拷贝/移动(持有路径所有权)。
80+ class DebugfsMount {
81+ public:
82+ explicit DebugfsMount (const char * root) : root_(root) {}
83+
84+ ~DebugfsMount () {
85+ if (!enable_path_.empty ()) {
86+ write_file (enable_path_.c_str (), " 0" );
87+ }
88+ umount (root_.c_str ());
89+ rmdir (root_.c_str ());
90+ }
91+
92+ DebugfsMount (const DebugfsMount&) = delete ;
93+ DebugfsMount& operator =(const DebugfsMount&) = delete ;
94+
95+ // 在事件成功 enable 后调用:析构时把该文件写回 "0"。
96+ void arm_enable (const char * enable_path) { enable_path_ = enable_path; }
97+
98+ private:
99+ std::string root_;
100+ std::string enable_path_;
101+ };
102+
67103// 子模式:被 execve 进来后立即退出 0。
68104[[noreturn]] void helper_exec_exit0 () {
69105 char arg0[] = " /proc/self/exe" ;
@@ -100,7 +136,8 @@ TEST(SchedProcessExecTp, EventFilesExist) {
100136 snprintf (root, sizeof (root), " /tmp/sched_tp_events_%d" , getpid ());
101137 ASSERT_EQ (0 , mkdir (root, 0755 )) << strerror (errno);
102138
103- mount_debugfs (root);
139+ ASSERT_TRUE (mount_debugfs (root)); // Thread7:mount 失败终止测试。
140+ DebugfsMount guard (root); // Thread8:RAII,任意提前 return 都 umount + rmdir。
104141
105142 const char * base_rel = " /tracing/events/sched/sched_process_exec" ;
106143 char base[256 ] = {};
@@ -145,8 +182,7 @@ TEST(SchedProcessExecTp, EventFilesExist) {
145182 EXPECT_EQ (end != nullptr && *end == ' \0 ' , true ) << " id has trailing garbage: " << id;
146183 EXPECT_GE (idval, 0 ) << " invalid id: " << id;
147184
148- EXPECT_EQ (0 , umount (root)) << strerror (errno);
149- EXPECT_EQ (0 , rmdir (root)) << strerror (errno);
185+ // 清理由 RAII guard 析构完成(umount + rmdir;本测例未 enable,无需 disable)。
150186}
151187
152188// enable 后 execve 应触发事件,trace 文件留下记录。
@@ -155,7 +191,8 @@ TEST(SchedProcessExecTp, FiresOnExecve) {
155191 snprintf (root, sizeof (root), " /tmp/sched_tp_fire_%d" , getpid ());
156192 ASSERT_EQ (0 , mkdir (root, 0755 )) << strerror (errno);
157193
158- mount_debugfs (root);
194+ ASSERT_TRUE (mount_debugfs (root)); // Thread7:mount 失败终止测试。
195+ DebugfsMount guard (root); // Thread8:RAII,析构 umount + rmdir。
159196
160197 const char * base_rel = " /tracing/events/sched/sched_process_exec" ;
161198 char base[256 ] = {};
@@ -165,6 +202,7 @@ TEST(SchedProcessExecTp, FiresOnExecve) {
165202 char enable_path[320 ] = {};
166203 snprintf (enable_path, sizeof (enable_path), " %s/enable" , base);
167204 ASSERT_TRUE (write_file (enable_path, " 1" )) << " enable write failed" ;
205+ guard.arm_enable (enable_path); // Thread8:任意提前 return 析构都会写回 "0"。
168206
169207 // 清空 ring buffer:向 trace 写任意字节触发 clear。
170208 char trace_path[256 ] = {};
@@ -194,10 +232,7 @@ TEST(SchedProcessExecTp, FiresOnExecve) {
194232 << " trace missing comm= field:\n "
195233 << trace;
196234
197- // 关闭事件并清理。
198- write_file (enable_path, " 0" );
199- EXPECT_EQ (0 , umount (root)) << strerror (errno);
200- EXPECT_EQ (0 , rmdir (root)) << strerror (errno);
235+ // 清理由 RAII guard 析构完成(disable + umount + rmdir)。
201236}
202237
203238// 默认 disabled 时 execve 不应在 trace 留下 sched_process_exec 记录。
@@ -207,7 +242,8 @@ TEST(SchedProcessExecTp, DefaultDisabledNoRecords) {
207242 snprintf (root, sizeof (root), " /tmp/sched_tp_disabled_%d" , getpid ());
208243 ASSERT_EQ (0 , mkdir (root, 0755 )) << strerror (errno);
209244
210- mount_debugfs (root);
245+ ASSERT_TRUE (mount_debugfs (root)); // Thread7:mount 失败终止测试。
246+ DebugfsMount guard (root); // Thread8:RAII,析构 umount + rmdir(本测例不 enable)。
211247
212248 char trace_path[256 ] = {};
213249 snprintf (trace_path, sizeof (trace_path), " %s/tracing/trace" , root);
@@ -233,8 +269,7 @@ TEST(SchedProcessExecTp, DefaultDisabledNoRecords) {
233269 << " tracepoint fired while disabled (static-key gate broken):\n "
234270 << trace;
235271
236- EXPECT_EQ (0 , umount (root)) << strerror (errno);
237- EXPECT_EQ (0 , rmdir (root)) << strerror (errno);
272+ // 清理由 RAII guard 析构完成(umount + rmdir;本测例未 enable,无需 disable)。
238273}
239274
240275// enable 后能触发,disable 后不再触发。验证 enable/disable 状态机真正翻转 static-key。
@@ -243,7 +278,8 @@ TEST(SchedProcessExecTp, DisableStopsFiring) {
243278 snprintf (root, sizeof (root), " /tmp/sched_tp_disable_%d" , getpid ());
244279 ASSERT_EQ (0 , mkdir (root, 0755 )) << strerror (errno);
245280
246- mount_debugfs (root);
281+ ASSERT_TRUE (mount_debugfs (root)); // Thread7:mount 失败终止测试。
282+ DebugfsMount guard (root); // Thread8:RAII,析构 umount + rmdir。
247283
248284 const char * base_rel = " /tracing/events/sched/sched_process_exec" ;
249285 char base[256 ] = {};
@@ -256,6 +292,7 @@ TEST(SchedProcessExecTp, DisableStopsFiring) {
256292
257293 // 基线:enable 后触发。
258294 ASSERT_TRUE (write_file (enable_path, " 1" )) << " enable write failed" ;
295+ guard.arm_enable (enable_path); // Thread8:任意提前 return 析构都会写回 "0"。
259296 ASSERT_TRUE (write_file (trace_path, " 1" )) << " trace clear write failed" ;
260297 {
261298 pid_t child = fork ();
@@ -297,8 +334,7 @@ TEST(SchedProcessExecTp, DisableStopsFiring) {
297334 << trace;
298335 }
299336
300- EXPECT_EQ (0 , umount (root)) << strerror (errno);
301- EXPECT_EQ (0 , rmdir (root)) << strerror (errno);
337+ // 清理由 RAII guard 析构完成(disable + umount + rmdir;析构再次写 "0" 对已 disable 状态幂等)。
302338}
303339
304340// non-leader 线程 execve:触发 de_thread 的 raw_pid 交换,old_pid ≠ pid。
@@ -308,7 +344,8 @@ TEST(SchedProcessExecTp, NonLeaderExecFiresWithDistinctOldPid) {
308344 snprintf (root, sizeof (root), " /tmp/sched_tp_nonleader_%d" , getpid ());
309345 ASSERT_EQ (0 , mkdir (root, 0755 )) << strerror (errno);
310346
311- mount_debugfs (root);
347+ ASSERT_TRUE (mount_debugfs (root)); // Thread7:mount 失败终止测试。
348+ DebugfsMount guard (root); // Thread8:RAII,析构 umount + rmdir。
312349
313350 const char * base_rel = " /tracing/events/sched/sched_process_exec" ;
314351 char base[256 ] = {};
@@ -320,6 +357,7 @@ TEST(SchedProcessExecTp, NonLeaderExecFiresWithDistinctOldPid) {
320357 snprintf (trace_path, sizeof (trace_path), " %s/tracing/trace" , root);
321358
322359 ASSERT_TRUE (write_file (enable_path, " 1" )) << " enable write failed" ;
360+ guard.arm_enable (enable_path); // Thread8:任意提前 return 析构都会写回 "0"。
323361 ASSERT_TRUE (write_file (trace_path, " 1" )) << " trace clear write failed" ;
324362
325363 // fork child:child 创建 sibling 线程(非 leader)执行 execve,leader 永久挂起。
@@ -363,9 +401,7 @@ TEST(SchedProcessExecTp, NonLeaderExecFiresWithDistinctOldPid) {
363401 << " non-leader exec should produce distinct old_pid vs pid:\n "
364402 << record;
365403
366- write_file (enable_path, " 0" );
367- EXPECT_EQ (0 , umount (root)) << strerror (errno);
368- EXPECT_EQ (0 , rmdir (root)) << strerror (errno);
404+ // 清理由 RAII guard 析构完成(disable + umount + rmdir)。
369405}
370406
371407int main (int argc, char ** argv) {
0 commit comments