1 /*
2  * Copyright (c) 2021-2023 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 #ifndef DFX_DUMPCATCH_H
17 #define DFX_DUMPCATCH_H
18 
19 #include <cinttypes>
20 #include <condition_variable>
21 #include <cstring>
22 #include <memory>
23 #include <mutex>
24 #include <string>
25 #include <unistd.h>
26 #include <vector>
27 
28 namespace OHOS {
29 namespace HiviewDFX {
30 static const size_t DEFAULT_MAX_FRAME_NUM = 256;
31 class DfxDumpCatcher {
32 public:
DfxDumpCatcher()33     DfxDumpCatcher() {}
~DfxDumpCatcher()34     ~DfxDumpCatcher() {}
35 
36     /**
37      * @brief Dump native stack by specify pid and tid
38      *
39      * @param pid  process id
40      * @param tid  thread id
41      * @param msg  message of native stack
42      * @param maxFrameNums the maximum number of frames to dump, if pid is not equal to caller pid then it is ignored
43      * @param isJson whether message of native stack is json formatted
44      * @return if succeed return true, otherwise return false
45     */
46     bool DumpCatch(int pid, int tid, std::string& msg, size_t maxFrameNums = DEFAULT_MAX_FRAME_NUM,
47                    bool isJson = false);
48 
49     /**
50      * @brief Dump native and js mixed-stack by specify pid and tid
51      *
52      * @param pid  process id
53      * @param tid  thread id
54      * @param msg  message of native and js mixed-stack
55      * @return if succeed return true, otherwise return false
56     */
57     bool DumpCatchMix(int pid, int tid, std::string& msg);
58 
59     /**
60      * @brief Dump native stack by specify pid and tid to file
61      *
62      * @param pid  process id
63      * @param tid  thread id
64      * @param fd  file descriptor
65      * @param maxFrameNums the maximum number of frames to dump,
66      *  if pid is not equal to caller pid then it does not support setting
67      * @return if succeed return true, otherwise return false
68     */
69     bool DumpCatchFd(int pid, int tid, std::string& msg, int fd, size_t maxFrameNums = DEFAULT_MAX_FRAME_NUM);
70 
71     /**
72      * @brief Dump native stack by multi-pid
73      *
74      * @param pid  process id
75      * @param tid  thread id
76      * @param msg  message of native stack
77      * @return if succeed return true, otherwise return false
78     */
79     bool DumpCatchMultiPid(const std::vector<int> pidV, std::string& msg);
80     /**
81      * @brief Dump stack of process
82      *
83      * @param pid  process id
84      * @param msg  message of stack
85      * @param maxFrameNums the maximum number of frames to dump,
86      *  if pid is not equal to caller pid then it does not support setting
87      * @param isJson whether message of stack is json formatted
88      * @return -1: dump catch failed 0:msg is normal stack 1:msg is kernel stack(not json format)
89     */
90     int DumpCatchProcess(int pid, std::string& msg, size_t maxFrameNums = DEFAULT_MAX_FRAME_NUM,
91         bool isJson = false);
92 private:
93     bool DoDumpCurrTid(const size_t skipFrameNum, std::string& msg, size_t maxFrameNums);
94     bool DoDumpLocalTid(const int tid, std::string& msg, size_t maxFrameNums);
95     bool DoDumpLocalPid(int pid, std::string& msg, size_t maxFrameNums);
96     bool DoDumpLocalLocked(int pid, int tid, std::string& msg, size_t maxFrameNums);
97     bool DoDumpRemoteLocked(int pid, int tid, std::string& msg, bool isJson = false,
98         int timeout = DUMPCATCHER_REMOTE_TIMEOUT);
99     bool DoDumpCatchRemote(int pid, int tid, std::string& msg, bool isJson = false,
100         int timeout = DUMPCATCHER_REMOTE_TIMEOUT);
101     int DoDumpRemotePid(int pid, std::string& msg, bool isJson = false, int32_t timeout = DUMPCATCHER_REMOTE_TIMEOUT);
102     int DoDumpRemotePoll(int bufFd, int resFd, int timeout, std::string& msg, bool isJson = false);
103     bool DoReadBuf(int fd, std::string& msg);
104     bool DoReadRes(int fd, bool &ret, std::string& msg);
105     static void CollectKernelStack(pid_t pid, int waitMilliSeconds = 0);
106     void AsyncGetAllTidKernelStack(pid_t pid, int waitMilliSeconds = 0);
107 
108 private:
109     static const int DUMPCATCHER_REMOTE_P90_TIMEOUT = 1000;
110     static const int DUMPCATCHER_REMOTE_TIMEOUT = 10000;
111     std::mutex mutex_;
112     int32_t pid_ = -1;
113     std::string halfProcStatus_ = "";
114     std::string halfProcWchan_ = "";
115 };
116 } // namespace HiviewDFX
117 } // namespace OHOS
118 
119 #endif
120