From bc6a7e51e4787bad7ab32c8ac4634eb99c477922 Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Fri, 18 Jan 2019 16:33:27 -0800 Subject: [PATCH] Fix flaky signal tests. The signal tests that send a SIGUSR1 signal to a remote process, can lead to a case where the code winds up in a location for which the unwind information is not 100% accurate. This happens near the end of the atomic functions which manipulate the stack right before returning, but do not have separate cfi instructions for those last few instructions. Add a new test type for the from_context test that will wait explicitly for the global g_finish and not piggy back on the remote test type. Bug: 122902885 Test: Ran flaky tests 1000 times without failure on a taimen. Change-Id: I7d0c9b016e3a3a2c0c0949cf74af11d7785a008c --- libunwindstack/tests/UnwindTest.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp index a91bd9506..c747eabc6 100644 --- a/libunwindstack/tests/UnwindTest.cpp +++ b/libunwindstack/tests/UnwindTest.cpp @@ -47,6 +47,7 @@ namespace unwindstack { enum TestTypeEnum : uint8_t { TEST_TYPE_LOCAL_UNWINDER = 0, TEST_TYPE_LOCAL_UNWINDER_FROM_PID, + TEST_TYPE_LOCAL_WAIT_FOR_FINISH, TEST_TYPE_REMOTE, TEST_TYPE_REMOTE_WITH_INVALID_CALL, }; @@ -79,7 +80,10 @@ static void SignalHandler(int, siginfo_t*, void* sigcontext) { extern "C" void SignalInnerFunction() { g_signal_ready_for_remote = true; - while (!g_finish.load()) { + // Avoid any function calls because not every instruction will be + // unwindable. + // This method of looping is only used when testing a remote unwind. + while (true) { } } @@ -134,6 +138,11 @@ static void VerifyUnwind(pid_t pid, Maps* maps, Regs* regs, // off. If this doesn't happen, then all of the calls will be optimized // away. extern "C" void InnerFunction(TestTypeEnum test_type) { + if (test_type == TEST_TYPE_LOCAL_WAIT_FOR_FINISH) { + while (!g_finish.load()) { + } + return; + } if (test_type == TEST_TYPE_REMOTE || test_type == TEST_TYPE_REMOTE_WITH_INVALID_CALL) { g_ready_for_remote = true; g_ready = true; @@ -141,7 +150,10 @@ extern "C" void InnerFunction(TestTypeEnum test_type) { void (*crash_func)() = nullptr; crash_func(); } - while (!g_finish.load()) { + // Avoid any function calls because not every instruction will be + // unwindable. + // This method of looping is only used when testing a remote unwind. + while (true) { } return; } @@ -271,7 +283,7 @@ TEST_F(UnwindTest, from_context) { std::atomic_int tid(0); std::thread thread([&]() { tid = syscall(__NR_gettid); - OuterFunction(TEST_TYPE_REMOTE); + OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH); }); struct sigaction act, oldact;