1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License. 5800b99b8Sopenharmony_ci * You may obtain a copy of the License at 6800b99b8Sopenharmony_ci * 7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8800b99b8Sopenharmony_ci * 9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and 13800b99b8Sopenharmony_ci * limitations under the License. 14800b99b8Sopenharmony_ci */ 15800b99b8Sopenharmony_ci 16800b99b8Sopenharmony_ci#include "dfx_process.h" 17800b99b8Sopenharmony_ci 18800b99b8Sopenharmony_ci#include <climits> 19800b99b8Sopenharmony_ci#include <cstdio> 20800b99b8Sopenharmony_ci#include <cstdlib> 21800b99b8Sopenharmony_ci#include <cstring> 22800b99b8Sopenharmony_ci#include <dirent.h> 23800b99b8Sopenharmony_ci#include <securec.h> 24800b99b8Sopenharmony_ci#include <sys/types.h> 25800b99b8Sopenharmony_ci#include <sys/sysinfo.h> 26800b99b8Sopenharmony_ci#include <unistd.h> 27800b99b8Sopenharmony_ci#include <vector> 28800b99b8Sopenharmony_ci 29800b99b8Sopenharmony_ci#include "dfx_config.h" 30800b99b8Sopenharmony_ci#include "dfx_define.h" 31800b99b8Sopenharmony_ci#include "dfx_logger.h" 32800b99b8Sopenharmony_ci#include "dfx_ring_buffer_wrapper.h" 33800b99b8Sopenharmony_ci#include "dfx_signal.h" 34800b99b8Sopenharmony_ci#include "dfx_util.h" 35800b99b8Sopenharmony_ci#include "procinfo.h" 36800b99b8Sopenharmony_ci#include "unique_fd.h" 37800b99b8Sopenharmony_ci 38800b99b8Sopenharmony_cinamespace OHOS { 39800b99b8Sopenharmony_cinamespace HiviewDFX { 40800b99b8Sopenharmony_cistd::shared_ptr<DfxProcess> DfxProcess::Create(pid_t pid, pid_t nsPid) 41800b99b8Sopenharmony_ci{ 42800b99b8Sopenharmony_ci auto process = std::make_shared<DfxProcess>(pid, nsPid); 43800b99b8Sopenharmony_ci return process; 44800b99b8Sopenharmony_ci} 45800b99b8Sopenharmony_ci 46800b99b8Sopenharmony_ciDfxProcess::DfxProcess(pid_t pid, pid_t nsPid) 47800b99b8Sopenharmony_ci{ 48800b99b8Sopenharmony_ci InitProcessInfo(pid, nsPid); 49800b99b8Sopenharmony_ci} 50800b99b8Sopenharmony_ci 51800b99b8Sopenharmony_civoid DfxProcess::InitProcessInfo(pid_t pid, pid_t nsPid) 52800b99b8Sopenharmony_ci{ 53800b99b8Sopenharmony_ci processInfo_.pid = pid; 54800b99b8Sopenharmony_ci processInfo_.nsPid = nsPid; 55800b99b8Sopenharmony_ci ReadProcessName(processInfo_.pid, processInfo_.processName); 56800b99b8Sopenharmony_ci} 57800b99b8Sopenharmony_ci 58800b99b8Sopenharmony_cibool DfxProcess::InitOtherThreads(bool attach) 59800b99b8Sopenharmony_ci{ 60800b99b8Sopenharmony_ci std::vector<int> tids; 61800b99b8Sopenharmony_ci std::vector<int> nstids; 62800b99b8Sopenharmony_ci if (!GetTidsByPid(processInfo_.pid, tids, nstids)) { 63800b99b8Sopenharmony_ci return false; 64800b99b8Sopenharmony_ci } 65800b99b8Sopenharmony_ci 66800b99b8Sopenharmony_ci for (size_t i = 0; i < nstids.size(); ++i) { 67800b99b8Sopenharmony_ci if ((recycleTid_ > 0) && (nstids[i] == static_cast<int>(recycleTid_))) { 68800b99b8Sopenharmony_ci DFXLOGD("skip recycle thread:%{public}d.", nstids[i]); 69800b99b8Sopenharmony_ci continue; 70800b99b8Sopenharmony_ci } 71800b99b8Sopenharmony_ci 72800b99b8Sopenharmony_ci if ((keyThread_ != nullptr) && nstids[i] == keyThread_->threadInfo_.nsTid) { 73800b99b8Sopenharmony_ci DFXLOGD("skip key thread:%{public}d.", nstids[i]); 74800b99b8Sopenharmony_ci continue; 75800b99b8Sopenharmony_ci } 76800b99b8Sopenharmony_ci 77800b99b8Sopenharmony_ci auto thread = DfxThread::Create(processInfo_.pid, tids[i], nstids[i]); 78800b99b8Sopenharmony_ci if (attach) { 79800b99b8Sopenharmony_ci thread->Attach(PTRACE_ATTATCH_OTHER_THREAD_TIMEOUT); 80800b99b8Sopenharmony_ci } 81800b99b8Sopenharmony_ci otherThreads_.push_back(thread); 82800b99b8Sopenharmony_ci } 83800b99b8Sopenharmony_ci return true; 84800b99b8Sopenharmony_ci} 85800b99b8Sopenharmony_ci 86800b99b8Sopenharmony_cipid_t DfxProcess::ChangeTid(pid_t tid, bool ns) 87800b99b8Sopenharmony_ci{ 88800b99b8Sopenharmony_ci if (processInfo_.pid == processInfo_.nsPid) { 89800b99b8Sopenharmony_ci return tid; 90800b99b8Sopenharmony_ci } 91800b99b8Sopenharmony_ci 92800b99b8Sopenharmony_ci if (kvThreads_.empty()) { 93800b99b8Sopenharmony_ci std::vector<int> tids; 94800b99b8Sopenharmony_ci std::vector<int> nstids; 95800b99b8Sopenharmony_ci if (!GetTidsByPid(processInfo_.pid, tids, nstids)) { 96800b99b8Sopenharmony_ci return tid; 97800b99b8Sopenharmony_ci } 98800b99b8Sopenharmony_ci for (size_t i = 0; i < nstids.size(); ++i) { 99800b99b8Sopenharmony_ci kvThreads_[nstids[i]] = tids[i]; 100800b99b8Sopenharmony_ci } 101800b99b8Sopenharmony_ci } 102800b99b8Sopenharmony_ci 103800b99b8Sopenharmony_ci for (auto iter = kvThreads_.begin(); iter != kvThreads_.end(); iter++) { 104800b99b8Sopenharmony_ci if (ns && (iter->first == tid)) { 105800b99b8Sopenharmony_ci return iter->second; 106800b99b8Sopenharmony_ci } 107800b99b8Sopenharmony_ci if (!ns && (iter->second == tid)) { 108800b99b8Sopenharmony_ci return iter->first; 109800b99b8Sopenharmony_ci } 110800b99b8Sopenharmony_ci } 111800b99b8Sopenharmony_ci return tid; 112800b99b8Sopenharmony_ci} 113800b99b8Sopenharmony_ci 114800b99b8Sopenharmony_cistd::vector<std::shared_ptr<DfxThread>>& DfxProcess::GetOtherThreads() 115800b99b8Sopenharmony_ci{ 116800b99b8Sopenharmony_ci return otherThreads_; 117800b99b8Sopenharmony_ci} 118800b99b8Sopenharmony_ci 119800b99b8Sopenharmony_civoid DfxProcess::ClearOtherThreads() 120800b99b8Sopenharmony_ci{ 121800b99b8Sopenharmony_ci otherThreads_.clear(); 122800b99b8Sopenharmony_ci} 123800b99b8Sopenharmony_ci 124800b99b8Sopenharmony_civoid DfxProcess::Attach(bool hasKey) 125800b99b8Sopenharmony_ci{ 126800b99b8Sopenharmony_ci if (hasKey && keyThread_) { 127800b99b8Sopenharmony_ci keyThread_->Attach(PTRACE_ATTATCH_KEY_THREAD_TIMEOUT); 128800b99b8Sopenharmony_ci } 129800b99b8Sopenharmony_ci 130800b99b8Sopenharmony_ci if (otherThreads_.empty()) { 131800b99b8Sopenharmony_ci return; 132800b99b8Sopenharmony_ci } 133800b99b8Sopenharmony_ci for (auto thread : otherThreads_) { 134800b99b8Sopenharmony_ci if (thread->threadInfo_.nsTid == processInfo_.nsPid) { 135800b99b8Sopenharmony_ci thread->Attach(PTRACE_ATTATCH_KEY_THREAD_TIMEOUT); 136800b99b8Sopenharmony_ci continue; 137800b99b8Sopenharmony_ci } 138800b99b8Sopenharmony_ci thread->Attach(PTRACE_ATTATCH_OTHER_THREAD_TIMEOUT); 139800b99b8Sopenharmony_ci } 140800b99b8Sopenharmony_ci} 141800b99b8Sopenharmony_ci 142800b99b8Sopenharmony_civoid DfxProcess::Detach() 143800b99b8Sopenharmony_ci{ 144800b99b8Sopenharmony_ci if (otherThreads_.empty()) { 145800b99b8Sopenharmony_ci return; 146800b99b8Sopenharmony_ci } 147800b99b8Sopenharmony_ci 148800b99b8Sopenharmony_ci for (auto thread : otherThreads_) { 149800b99b8Sopenharmony_ci thread->Detach(); 150800b99b8Sopenharmony_ci } 151800b99b8Sopenharmony_ci} 152800b99b8Sopenharmony_ci 153800b99b8Sopenharmony_civoid DfxProcess::SetFatalMessage(const std::string &msg) 154800b99b8Sopenharmony_ci{ 155800b99b8Sopenharmony_ci fatalMsg_ = msg; 156800b99b8Sopenharmony_ci} 157800b99b8Sopenharmony_ci 158800b99b8Sopenharmony_cistd::string DfxProcess::GetFatalMessage() const 159800b99b8Sopenharmony_ci{ 160800b99b8Sopenharmony_ci return fatalMsg_; 161800b99b8Sopenharmony_ci} 162800b99b8Sopenharmony_ci 163800b99b8Sopenharmony_cinamespace { 164800b99b8Sopenharmony_cibool GetProcessInfo(pid_t tid, unsigned long long &startTime) 165800b99b8Sopenharmony_ci{ 166800b99b8Sopenharmony_ci std::string path = "/proc/" +std::to_string(tid); 167800b99b8Sopenharmony_ci UniqueFd dirFd(open(path.c_str(), O_DIRECTORY | O_RDONLY)); 168800b99b8Sopenharmony_ci if (dirFd == -1) { 169800b99b8Sopenharmony_ci return false; 170800b99b8Sopenharmony_ci } 171800b99b8Sopenharmony_ci 172800b99b8Sopenharmony_ci UniqueFd statFd(openat(dirFd.Get(), "stat", O_RDONLY | O_CLOEXEC)); 173800b99b8Sopenharmony_ci if (statFd == -1) { 174800b99b8Sopenharmony_ci return false; 175800b99b8Sopenharmony_ci } 176800b99b8Sopenharmony_ci 177800b99b8Sopenharmony_ci std::string statStr; 178800b99b8Sopenharmony_ci if (!ReadFdToString(statFd.Get(), statStr)) { 179800b99b8Sopenharmony_ci return false; 180800b99b8Sopenharmony_ci } 181800b99b8Sopenharmony_ci 182800b99b8Sopenharmony_ci std::string eoc = statStr.substr(statStr.find_last_of(")")); 183800b99b8Sopenharmony_ci std::istringstream is(eoc); 184800b99b8Sopenharmony_ci constexpr int startTimePos = 21; 185800b99b8Sopenharmony_ci constexpr int base = 10; 186800b99b8Sopenharmony_ci int pos = 0; 187800b99b8Sopenharmony_ci std::string tmp; 188800b99b8Sopenharmony_ci while (is >> tmp && pos <= startTimePos) { 189800b99b8Sopenharmony_ci pos++; 190800b99b8Sopenharmony_ci if (pos == startTimePos) { 191800b99b8Sopenharmony_ci startTime = strtoull(tmp.c_str(), nullptr, base); 192800b99b8Sopenharmony_ci return true; 193800b99b8Sopenharmony_ci } 194800b99b8Sopenharmony_ci } 195800b99b8Sopenharmony_ci return false; 196800b99b8Sopenharmony_ci} 197800b99b8Sopenharmony_ci} 198800b99b8Sopenharmony_ci 199800b99b8Sopenharmony_cistd::string DfxProcess::GetProcessLifeCycle(pid_t pid) 200800b99b8Sopenharmony_ci{ 201800b99b8Sopenharmony_ci struct sysinfo si; 202800b99b8Sopenharmony_ci sysinfo(&si); 203800b99b8Sopenharmony_ci unsigned long long startTime = 0; 204800b99b8Sopenharmony_ci if (GetProcessInfo(pid, startTime)) { 205800b99b8Sopenharmony_ci if (sysconf(_SC_CLK_TCK) == -1) { 206800b99b8Sopenharmony_ci return ""; 207800b99b8Sopenharmony_ci } 208800b99b8Sopenharmony_ci uint64_t upTime = si.uptime - startTime / static_cast<uint32_t>(sysconf(_SC_CLK_TCK)); 209800b99b8Sopenharmony_ci return std::to_string(upTime) + "s"; 210800b99b8Sopenharmony_ci } 211800b99b8Sopenharmony_ci return ""; 212800b99b8Sopenharmony_ci} 213800b99b8Sopenharmony_ci} // namespace HiviewDFX 214800b99b8Sopenharmony_ci} // namespace OHOS 215