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