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
32namespace panda {
33void 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
60int 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