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 <poll.h> 25 #include <string> 26 #include <unistd.h> 27 #include <vector> 28 29 #include "dfx_dump_catcher_errno.h" 30 31 namespace OHOS { 32 namespace HiviewDFX { 33 class DfxDumpCatcher { 34 public: 35 /** 36 * @brief Dump native stack by specify pid and tid 37 * 38 * @param pid process id 39 * @param tid thread id 40 * @param msg message of native stack 41 * @param maxFrameNums the maximum number of frames to dump, if pid is not equal to caller pid then it is ignored 42 * @param isJson whether message of native stack is json formatted 43 * @return if succeed return true, otherwise return false 44 */ 45 bool DumpCatch(int pid, int tid, std::string& msg, size_t maxFrameNums = DEFAULT_MAX_FRAME_NUM, 46 bool isJson = false); 47 48 /** 49 * @brief Dump native stack by specify pid and tid to file 50 * 51 * @param pid process id 52 * @param tid thread id 53 * @param fd file descriptor 54 * @param maxFrameNums the maximum number of frames to dump, 55 * if pid is not equal to caller pid then it does not support setting 56 * @return if succeed return true, otherwise return false 57 */ 58 bool DumpCatchFd(int pid, int tid, std::string& msg, int fd, size_t maxFrameNums = DEFAULT_MAX_FRAME_NUM); 59 60 /** 61 * @brief Dump native stack by multi-pid 62 * 63 * @param pid process id 64 * @param tid thread id 65 * @param msg message of native stack 66 * @return if succeed return true, otherwise return false 67 */ 68 bool DumpCatchMultiPid(const std::vector<int> pidV, std::string& msg); 69 /** 70 * @brief Dump stack of process 71 * 72 * @param pid process id 73 * @param msg message of stack 74 * @param maxFrameNums the maximum number of frames to dump, 75 * if pid is not equal to caller pid then it does not support setting 76 * @param isJson whether message of stack is json formatted 77 * @return -1: dump catch failed 0:msg is normal stack 1:msg is kernel stack(not json format) 78 */ 79 int DumpCatchProcess(int pid, std::string& msg, size_t maxFrameNums = DEFAULT_MAX_FRAME_NUM, 80 bool isJson = false); 81 /** 82 * @brief Dump stack of process with timeout 83 * 84 * @param pid process id 85 * @param msg message of stack 86 * @param timeout Set the dump timeout time to be at least 1000ms 87 * @param isJson whether message of stack is json formatted 88 * @return ret and reason. 89 * ret: -1: dump catch failed 0:msg is normal stack 1:msg is kernel stack(not json format) 90 * reason: if ret is 1, it contains normal stack fail reason. 91 * if ret is -1, it contains normal stack fail reason and kernel stack fail reason. 92 */ 93 std::pair<int, std::string> DumpCatchWithTimeout(int pid, std::string& msg, int timeout = 3000, 94 int tid = 0, bool isJson = false); 95 private: 96 static constexpr size_t DEFAULT_MAX_FRAME_NUM = 256; 97 bool DoDumpCurrTid(const size_t skipFrameNum, std::string& msg, size_t maxFrameNums); 98 bool DoDumpLocalTid(const int tid, std::string& msg, size_t maxFrameNums); 99 bool DoDumpLocalPid(int pid, std::string& msg, size_t maxFrameNums); 100 bool DoDumpLocalLocked(int pid, int tid, std::string& msg, size_t maxFrameNums); 101 int32_t DoDumpRemoteLocked(int pid, int tid, std::string& msg, bool isJson = false, 102 int timeout = DUMPCATCHER_REMOTE_TIMEOUT); 103 int32_t DoDumpCatchRemote(int pid, int tid, std::string& msg, bool isJson = false, 104 int timeout = DUMPCATCHER_REMOTE_TIMEOUT); 105 int DoDumpRemotePid(int pid, std::string& msg, int (&pipeReadFd)[2], 106 bool isJson = false, int32_t timeout = DUMPCATCHER_REMOTE_TIMEOUT); 107 bool HandlePollError(const uint64_t endTime, int& remainTime, 108 bool& collectAllTidStack, std::string& resMsg, int& ret); 109 bool HandlePollTimeout(const int timeout, int& remainTime, 110 bool& collectAllTidStack, std::string& resMsg, int& ret); 111 bool HandlePollEvents(std::pair<int, std::string>& bufState, std::pair<int, std::string>& resState, 112 const struct pollfd (&readFds)[2], bool& bPipeConnect, bool& res); 113 std::pair<bool, int> DumpRemotePoll(const int timeout, std::pair<int, std::string>& bufState, 114 std::pair<int, std::string>& resState); 115 int DoDumpRemotePoll(int timeout, std::string& msg, const int (&pipeReadFd)[2], bool isJson = false); 116 bool DoReadBuf(int fd, std::string& msg); 117 bool DoReadRes(int fd, bool& ret, std::string& msg); 118 static void CollectKernelStack(pid_t pid, int waitMilliSeconds = 0); 119 void AsyncGetAllTidKernelStack(pid_t pid, int waitMilliSeconds = 0); 120 void DealWithPollRet(int pollRet, int pid, int32_t& ret, std::string& msg); 121 void DealWithSdkDumpRet(int sdkdumpRet, int pid, int32_t& ret, std::string& msg); 122 123 private: 124 static const int DUMPCATCHER_REMOTE_P90_TIMEOUT = 1000; 125 static const int DUMPCATCHER_REMOTE_TIMEOUT = 10000; 126 std::mutex mutex_; 127 int32_t pid_ = -1; 128 std::string halfProcStatus_ = ""; 129 std::string halfProcWchan_ = ""; 130 }; 131 } // namespace HiviewDFX 132 } // namespace OHOS 133 134 #endif 135