1 /**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <unistd.h>
17 #include <csignal>
18 #include <sys/prctl.h>
19 #include <gtest/gtest.h>
20
21 #if !defined(TIMEOUT_SIGNAL)
22 #error "TIMEOUT_SIGNAL is not defined"
23 #endif
24 #if !defined(GDB_PATH)
25 #error "GDB_PATH is not defined"
26 #else
27 #define XSTR(x) STR(x)
28 #define STR(x) #x
29 #define GDB_PATH_STR XSTR(GDB_PATH)
30 #endif
31
32 namespace panda {
HandleTimeout(int sig)33 void HandleTimeout(int sig)
34 {
35 if (sig != TIMEOUT_SIGNAL) {
36 return;
37 }
38
39 // Allow to attach gdb.
40 // Do it before fork because the child can attach gdb before
41 // the parent allows it.
42 prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);
43 pid_t pid = fork();
44 if (pid != 0) {
45 // Parent
46 raise(SIGSTOP); // wait for child's gdb invocation to pick us up
47 } else {
48 // Child
49 std::stringstream out;
50 out << getppid();
51 std::string ppid_str = out.str();
52 execlp(GDB_PATH_STR, "-q", "--batch",
53 "-p", ppid_str.c_str(),
54 "-ex", "info threads",
55 "-ex", "thread apply all bt",
56 "-ex", "kill", nullptr);
57 }
58 }
59
main(int argc,char * argv[])60 int main(int argc, char *argv[])
61 {
62 signal(TIMEOUT_SIGNAL, HandleTimeout);
63 testing::InitGoogleTest(&argc, argv);
64 return RUN_ALL_TESTS();
65 }
66 } // namespace panda
67