unw_backtrace is not async-signal-safe
[folly.git] / folly / experimental / symbolizer / test / StackTraceTest.cpp
1 /*
2  * Copyright 2013 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "folly/experimental/symbolizer/StackTrace.h"
18 #include "folly/experimental/symbolizer/Symbolizer.h"
19
20 #include <glog/logging.h>
21 #include <gtest/gtest.h>
22
23 using namespace folly;
24 using namespace folly::symbolizer;
25
26 void foo1() __attribute__((noinline));
27 void foo2() __attribute__((noinline));
28
29 void verifyStackTraces() {
30   constexpr size_t kMaxAddresses = 100;
31   FrameArray<kMaxAddresses> fa;
32   CHECK(getStackTrace(fa));
33
34   FrameArray<kMaxAddresses> faSafe;
35   CHECK(getStackTraceSafe(faSafe));
36
37   CHECK_EQ(fa.frameCount, faSafe.frameCount);
38
39   // Other than the top 2 frames (this one and getStackTrace /
40   // getStackTraceSafe), the stack traces should be identical
41   for (size_t i = 2; i < fa.frameCount; ++i) {
42     VLOG(1) << "i=" << i << " " << std::hex << fa.addresses[i] << " "
43             << faSafe.addresses[i];
44     CHECK_EQ(fa.addresses[i], faSafe.addresses[i]);
45   }
46 }
47
48 void foo1() {
49   foo2();
50 }
51
52 void foo2() {
53   verifyStackTraces();
54 }
55
56 volatile bool handled = false;
57 void handler(int num, siginfo_t* info, void* ctx) {
58   // Yes, getStackTrace and VLOG aren't async-signal-safe, but signals
59   // raised with raise() aren't "async" signals.
60   foo1();
61   handled = true;
62 }
63
64 TEST(StackTraceTest, Simple) {
65   foo1();
66 }
67
68 TEST(StackTraceTest, Signal) {
69   struct sigaction sa;
70   memset(&sa, 0, sizeof(sa));
71   sa.sa_sigaction = handler;
72   sa.sa_flags = SA_RESETHAND | SA_SIGINFO;
73   CHECK_ERR(sigaction(SIGUSR1, &sa, nullptr));
74   raise(SIGUSR1);
75   CHECK(handled);
76 }
77
78 int main(int argc, char *argv[]) {
79   testing::InitGoogleTest(&argc, argv);
80   google::ParseCommandLineFlags(&argc, &argv, true);
81   return RUN_ALL_TESTS();
82 }
83