gdb/testsuite: Add runtime-core-attached test - #216
Conversation
6262869 to
3d062bb
Compare
lancesix
left a comment
There was a problem hiding this comment.
Some preliminary comments. Will do a more in depth review later.
16e1248 to
6fa15be
Compare
51b440f to
5108ffd
Compare
lumachad
left a comment
There was a problem hiding this comment.
Could we please have a better description of what we're trying to test here? The "test core dump while gdb is attached" sounded to me like we were controlling rocgdb when generating the core file, but it sounds like what we want is for some unrelated process to be generating a core file while we test something else in the runtime.
Is that the case? If so, should this be a ROCR test instead?
be3797f to
3e11ade
Compare
531654b to
2b99b98
Compare
| gdb_test "handle SIGABRT nostop pass" ".*" | ||
| gdb_test "handle SIGSEGV nostop pass" ".*" | ||
| gdb_test_no_output "set cwd $coredir" | ||
| gdb_test "set args $fault" ".*" |
There was a problem hiding this comment.
Done. Changed to gdb_test_no_output "set args $fault" on line 53.
| # a while for large core dumps. | ||
| with_timeout_factor 3 { | ||
| gdb_test_multiple "" "wait for program exit" { | ||
| -re "Program terminated with signal" { |
There was a problem hiding this comment.
Multiple messages arrive before the prompt (both "Program terminated" and "The program no longer exists"), so
-wrap on each pattern causes race conditions; using exp_continue for messages and matching the final prompt
directly works correctly.
| with_timeout_factor 3 { | ||
| gdb_test_multiple "" "wait for program exit" { | ||
| -re "Program terminated with signal" { | ||
| pass "program crashed" |
There was a problem hiding this comment.
Let's please use $gdb_test_name. Also in the occurrences below.
| gdb_test "target core $merged_core" \ | ||
| [multi_line \ | ||
| ".*" \ | ||
| "Core was generated by .*" \ |
There was a problem hiding this comment.
I feel uneasy about .*'s in such cases, because they can also match newline. Can we use \[\r\n\]* instead. Also in the line below.
There was a problem hiding this comment.
The pattern (lines 120-124) follows the established pattern from runtime-core.exp for matching core file loading output. The leading .* on line 121 is necessary to skip the library loading messages that precede "Core was generated by". The trailing .* patterns allow matching variable content (command arguments, signal details, wave coordinates). The multi_line structure with these patterns has been proven to work correctly in the sibling test.
37620ba to
5703c12
Compare
| require allow_rocm_core_tests | ||
| require allow_hip_tests | ||
|
|
||
| standard_testfile runtime-core.cpp |
There was a problem hiding this comment.
We usually try to have a 1:1 mapping between .ccp and .exp. Either what is tested here fits in runtime-core.exp, or this test should have its own test program.
There was a problem hiding this comment.
Sure, added runtime-core-attached.cpp
| # Check that ulimit allows core dumps. The test environment must | ||
| # have ulimit -c set to unlimited before running this test. | ||
| set ulimit_value [exec sh -c "ulimit -c"] | ||
| if {$ulimit_value != "unlimited"} { |
There was a problem hiding this comment.
I am not sure checking ulimit that way is sufficient. For example, if building GDB with ASAN, the ASAN runtime implicitly turns ulimit to 0 (the ASAN has a heavy impact on core size otherwise):
$ ulimit -c
unlimited
$ ASAN_OPTIONS=detect_leaks=0 ./gdb/gdb -data-directory ./gdb/data-directory -ex "shell ulimit -c" -q -batch
0
There was a problem hiding this comment.
I've removed the check, since runtime-core.exp does not check for it either.
5703c12 to
6fc6cb4
Compare
6fc6cb4 to
f5ecd1e
Compare
b35e2fd to
aad3169
Compare
Test core dump generation while program runs under GDB. What we're testing: 1. Run a HIP program under GDB 2. Configure GDB to pass signals through (not stop on them) 3. Program crashes with GPU fault 4. ROCm runtime generates core dumps even though GDB is attached 5. Verify GDB can load those cores and see GPU threads Uses batch mode: -ex 'handle SIGABRT/SIGSEGV nostop pass' -ex 'run' This allows GDB to catch faults but pass them to runtime/kernel.
aad3169 to
6dd0052
Compare
| #include <stdlib.h> | ||
| #include "gdb_watchdog.h" | ||
|
|
||
| #define CHECK(cmd) \ |
There was a problem hiding this comment.
Please use the version from rocm-test-utils.h.
| return -1 | ||
| } | ||
|
|
||
| proc do_attached_test { fault } { |
| return | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
This gdb_test_multiple seems much.
The "timeout" should be handled by default by gdb_test_multiple (or gdb_test), and the other cases only use exp_continue. All this matches is that we got the prompt back, which we could as well do with gdb_test "run" "The program no longer exists", couldn't we?.
| { | ||
| memfault, | ||
| abort | ||
| }; |
There was a problem hiding this comment.
abort as an enum member shadows the global ::abort() called by abort_kernel a few lines above. This compiles in C++ because the enum member is only in scope where the type is used as testcase_t::abort, but it is confusing and fragile. Rename it, e.g. kabort or do_abort, as is idiomatic in GDB test sources — see runtime-core.cpp which has the same pattern and the same risk.
| pagefault_kernel (int *out) | ||
| { | ||
| int local = 42; | ||
| *out = 8; |
There was a problem hiding this comment.
int local = 42 is unused by the test — unlike runtime-core.exp, this test never runs p local. Either remove it, or add a comment explaining it is intentionally left for future frame-variable checks (as runtime-core.cpp uses it). Same applies to abort_kernel (line 61) and aux_kernel (line 73).
|
|
||
| clean_restart $::testfile | ||
| gdb_test "handle SIGABRT nostop pass" ".*" | ||
| gdb_test "handle SIGSEGV nostop pass" ".*" |
There was a problem hiding this comment.
".*" as the expected pattern records no meaningful output check and produces a generic pass/fail. Use gdb_test_no_output if no output check is intended, or supply a real pattern such as "Signal.*SIGABRT.*No.*Yes.*" so the signal-handler table is at least spot-checked. Same for the SIGSEGV handle command on the next line.
| set hostcore [lindex $hostcore_list 0] | ||
|
|
||
| pass "generated both cores while gdb attached" | ||
|
|
There was a problem hiding this comment.
This pass fires before coremerge is invoked (line 100) and before gdb_assert checks that the merged core exists (line 101). A coremerge failure will still leave this pass on record. Move the pass to after the gdb_assert, or fold it into the assert message.
| set coremerge [gdb_find_coremerge] | ||
| set merged_core "$coredir/merged-$fault.core" | ||
| remote_exec build "$coremerge $merged_core $hostcore $gpucore" | ||
|
|
There was a problem hiding this comment.
The return value of remote_exec build "$coremerge ..." is ignored. If coremerge is not found or exits non-zero, the subsequent gdb_assert fires with a confusing message. Follow the pattern in rocm.exp:599-604: check [remote_file build exists $merged_core] immediately and emit a warning with the coremerge stderr if it is absent, then return early.
Test core dump generation while program runs under GDB. With the fix for core dump collection during debugging, verify that running under GDB in batch mode with signal passthrough generates both host and GPU cores, which can be merged and loaded.
What we're testing:
Uses batch mode: -ex 'handle SIGABRT/SIGSEGV nostop pass' -ex 'run' This allows GDB to catch faults but pass them to runtime/kernel.
Motivation
Tests the new capability from ROCm/rocm-systems#6811 that enables core dump generation even when a debugger is
attached
Technical Details
core.*) and GPU (core.*.gpu) cores are generatedsystemcommand to inherit test environment (LD_LIBRARY_PATH)