googletest icon indicating copy to clipboard operation
googletest copied to clipboard

Death tests: attempt to disable core dumps in child process.

Open cf-natali opened this issue 3 years ago • 2 comments

Disabling core dumps in the child process makes tests significantly faster if the process crashes while core dumps are enabled, in particular when the address space is large or dumping cores is slow because of e.g. compression or slow IO.

See this example calling ASSERT_DEATH with a raise(SIGABRT) 10 times, on my laptop with systemd-coredump enabled: Before:

$ ./googletest/googletest-death-test-test  --gtest_filter=*CoreDump*
Running main() from /home/cf/src/googletest/googletest/src/gtest_main.cc
Note: Google Test filter = *CoreDump*
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from TestForDeathTest
[ RUN      ] TestForDeathTest.TestFastDeathNoCoreDump
[       OK ] TestForDeathTest.TestFastDeathNoCoreDump (1339 ms)
[----------] 1 test from TestForDeathTest (1339 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (1339 ms total)
[  PASSED  ] 1 test.

After:

$ ./googletest/googletest-death-test-test  --gtest_filter=*CoreDump*
Running main() from /home/cf/src/googletest/googletest/src/gtest_main.cc
Note: Google Test filter = *CoreDump*
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from TestForDeathTest
[ RUN      ] TestForDeathTest.TestFastDeathNoCoreDump
[       OK ] TestForDeathTest.TestFastDeathNoCoreDump (4 ms)
[----------] 1 test from TestForDeathTest (4 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (4 ms total)
[  PASSED  ] 1 test.

And that's with a small address space, so in practice it can yield speedups over 1000X.

Note that the code uses prctl(PR_SET_DUMPABLE, 0) over setting RLIMIT_CORE to 0 when available, because the latter does not fully prevent generating core dumps on Linux, see https://lkml.org/lkml/2011/8/25/124 for background and the below example:

$ python3 -c "import os, faulthandler; print(os.getpid()); faulthandler._sigsegv()"; sleep 3; coredumpctl -rq | head -n2
75826
Segmentation fault (core dumped)
TIME                            PID   UID   GID SIG COREFILE  EXE
Sat 2022-08-27 10:07:19 BST   75826  1000  1000  11 present   /usr/bin/python3.9
$ ulimit -c 0; python3 -c "import os, faulthandler; print(os.getpid()); faulthandler._sigsegv()"; sleep 3; coredumpctl -rq | head -n2
76425
Segmentation fault (core dumped)
TIME                            PID   UID   GID SIG COREFILE  EXE
Sat 2022-08-27 10:07:31 BST   76425  1000  1000  11 present   /usr/bin/python3.9

cf-natali avatar Aug 27 '22 10:08 cf-natali

@cf-natali do you intend to make the changes that have been requested or should someone else pick up this work?

apcountryman avatar Mar 07 '24 19:03 apcountryman

Hey,

I'm sorry but I don't really have time to push this. It's actually complicated by the fact that gtest has two different ways to run subprocesses - fork and fork+exec, and in the latter case it seems that contrarily to the doc PR_SET_DUMPABLE is not inherited across execve. PR_SET_DUMPABLE also has some subtle side effects like making some files under /proc/pid/ inaccessible as regular users, which could be tricky for some workloads.

cf-natali avatar Apr 16 '24 18:04 cf-natali