1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
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/test/SignalHandlerTest.h>
18 
19 #include <folly/experimental/symbolizer/SignalHandler.h>
20 
21 #include <folly/CPortability.h>
22 #include <folly/FileUtil.h>
23 #include <folly/Range.h>
24 #include <folly/experimental/coro/BlockingWait.h>
25 #include <folly/experimental/coro/Task.h>
26 #include <folly/portability/GTest.h>
27 
28 #include <glog/logging.h>
29 
30 namespace folly {
31 namespace symbolizer {
32 namespace test {
33 
34 namespace {
35 
print(StringPiece sp)36 void print(StringPiece sp) {
37   writeFull(STDERR_FILENO, sp.data(), sp.size());
38 }
39 
callback1()40 void callback1() {
41   print("Callback1\n");
42 }
43 
callback2()44 void callback2() {
45   if (fatalSignalReceived()) {
46     print("Callback2\n");
47   }
48 }
49 
funcC()50 [[noreturn]] FOLLY_NOINLINE void funcC() {
51   LOG(FATAL) << "Die";
52 }
53 
co_funcB()54 FOLLY_NOINLINE folly::coro::Task<void> co_funcB() {
55   funcC();
56   co_return;
57 }
58 
co_funcA()59 FOLLY_NOINLINE folly::coro::Task<void> co_funcA() {
60   co_await co_funcB();
61 }
62 
63 } // namespace
64 
TEST(SignalHandler,Simple)65 TEST(SignalHandler, Simple) {
66   addFatalSignalCallback(callback1);
67   addFatalSignalCallback(callback2);
68   installFatalSignalHandler();
69   installFatalSignalCallbacks();
70 
71   EXPECT_FALSE(fatalSignalReceived());
72 
73   EXPECT_DEATH(
74       failHard(),
75       "^\\*\\*\\* Aborted at [0-9]+ \\(Unix time, try 'date -d @[0-9]+'\\) "
76       "\\*\\*\\*\n"
77       "\\*\\*\\* Signal 11 \\(SIGSEGV\\) \\(0x2a\\) received by PID [0-9]+ "
78       "\\(pthread TID 0x[0-9a-f]+\\) \\(linux TID [0-9]+\\) "
79       "\\(code: address not mapped to object\\), "
80       "stack trace: \\*\\*\\*\n"
81       ".*\n"
82       ".*    @ [0-9a-f]+.* folly::symbolizer::test::SignalHandler_Simple_Test"
83       "::TestBody\\(\\).*\n"
84       ".*\n"
85       ".*    @ [0-9a-f]+.* main.*\n"
86       ".*\n"
87       "Callback1\n"
88       "Callback2\n"
89       ".*");
90 }
91 
TEST(SignalHandler,AsyncStackTraceSimple)92 TEST(SignalHandler, AsyncStackTraceSimple) {
93   addFatalSignalCallback(callback1);
94   addFatalSignalCallback(callback2);
95   installFatalSignalHandler();
96   installFatalSignalCallbacks();
97 
98   EXPECT_DEATH(
99       folly::coro::blockingWait(co_funcA()),
100       "\\*\\*\\* Aborted at [0-9]+ \\(Unix time, try 'date -d @[0-9]+'\\) "
101       "\\*\\*\\*\n"
102       "\\*\\*\\* Signal 6 \\(SIGABRT\\) \\(0x[0-9a-f]+\\) received by PID [0-9]+ "
103       "\\(pthread TID 0x[0-9a-f]+\\) \\(linux TID [0-9]+\\) .*, "
104       "stack trace: \\*\\*\\*\n"
105       ".*\n"
106       ".*    @ [0-9a-f]+.* folly::symbolizer::test::SignalHandler"
107       "_AsyncStackTraceSimple_Test::TestBody\\(\\).*\n"
108       ".*\n"
109       ".*    @ [0-9a-f]+.* main.*\n"
110       ".*\n"
111       "\\*\\*\\* Check failure async stack trace: \\*\\*\\*\n"
112       "\\*\\*\\* First async stack root.* \\*\\*\\*\n"
113       "\\*\\*\\* First async stack frame pointer.* \\*\\*\\*\n"
114       ".*\n"
115       ".*    @ [0-9a-f]+.* folly::symbolizer::test::\\(anonymous namespace\\)"
116       "::funcC.*\n"
117       ".*\n"
118       ".*    @ [0-9a-f]+.* folly::symbolizer::test::\\(anonymous namespace\\)"
119       "::co_funcB.*\n"
120       ".*\n"
121       ".*    @ [0-9a-f]+.* folly::symbolizer::test::\\(anonymous namespace\\)"
122       "::co_funcA.*\n"
123       ".*\n"
124       "Callback1\n"
125       "Callback2\n"
126       ".*");
127 }
128 } // namespace test
129 } // namespace symbolizer
130 } // namespace folly
131 
132 // Can't use initFacebookLight since that would install its own signal handlers
133 // Can't use initFacebookNoSignals since we cannot depend on common
main(int argc,char ** argv)134 int main(int argc, char** argv) {
135   ::testing::InitGoogleTest(&argc, argv);
136   return RUN_ALL_TESTS();
137 }
138