1020a203aSopenharmony_ci/* 2020a203aSopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd. 3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4020a203aSopenharmony_ci * you may not use this file except in compliance with the License. 5020a203aSopenharmony_ci * You may obtain a copy of the License at 6020a203aSopenharmony_ci * 7020a203aSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8020a203aSopenharmony_ci * 9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12020a203aSopenharmony_ci * See the License for the specific language governing permissions and 13020a203aSopenharmony_ci * limitations under the License. 14020a203aSopenharmony_ci */ 15020a203aSopenharmony_ci#include "open_stacktrace_catcher.h" 16020a203aSopenharmony_ci 17020a203aSopenharmony_ci#include <ctime> 18020a203aSopenharmony_ci#include <string> 19020a203aSopenharmony_ci 20020a203aSopenharmony_ci#include "common_utils.h" 21020a203aSopenharmony_ci#include "file_util.h" 22020a203aSopenharmony_ci#include "log_catcher_utils.h" 23020a203aSopenharmony_ci#include "hiview_logger.h" 24020a203aSopenharmony_ci#include "securec.h" 25020a203aSopenharmony_ci#include <sys/wait.h> 26020a203aSopenharmony_ci#include <unistd.h> 27020a203aSopenharmony_ci 28020a203aSopenharmony_cinamespace OHOS { 29020a203aSopenharmony_cinamespace HiviewDFX { 30020a203aSopenharmony_cinamespace { 31020a203aSopenharmony_ci static const inline int SLEEP_TIME_US = 100000; 32020a203aSopenharmony_ci static const inline int MAX_RETRY_COUNT = 10; 33020a203aSopenharmony_ci} 34020a203aSopenharmony_ciDEFINE_LOG_LABEL(0xD002D01, "EventLogger-OpenStacktraceCatcher"); 35020a203aSopenharmony_ciOpenStacktraceCatcher::OpenStacktraceCatcher() : EventLogCatcher() 36020a203aSopenharmony_ci{ 37020a203aSopenharmony_ci name_ = "OpenStacktraceCatcher"; 38020a203aSopenharmony_ci} 39020a203aSopenharmony_ci 40020a203aSopenharmony_cibool OpenStacktraceCatcher::Initialize(const std::string& packageNam, int pid, int intParam) 41020a203aSopenharmony_ci{ 42020a203aSopenharmony_ci if (pid <= 0 && packageNam.length() == 0) { 43020a203aSopenharmony_ci description_ = "OpenStacktraceCatcher -- pid is null, packageName is null\n"; 44020a203aSopenharmony_ci return false; 45020a203aSopenharmony_ci } 46020a203aSopenharmony_ci packageName_ = packageNam; 47020a203aSopenharmony_ci if (pid > 0) { 48020a203aSopenharmony_ci pid_ = pid; 49020a203aSopenharmony_ci } else { 50020a203aSopenharmony_ci pid_ = CommonUtils::GetPidByName(packageNam); 51020a203aSopenharmony_ci } 52020a203aSopenharmony_ci 53020a203aSopenharmony_ci if (pid_ <= 0) { 54020a203aSopenharmony_ci description_ = "OpenStacktraceCatcher -- packageName is " + packageName_ + " pid is null\n"; 55020a203aSopenharmony_ci return false; 56020a203aSopenharmony_ci } 57020a203aSopenharmony_ci 58020a203aSopenharmony_ci if (packageName_.length() == 0) { 59020a203aSopenharmony_ci packageName_ = "(null)"; 60020a203aSopenharmony_ci } 61020a203aSopenharmony_ci 62020a203aSopenharmony_ci description_ = "OpenStacktraceCatcher -- pid==" + std::to_string(pid_) + " packageName is " + packageName_ + "\n"; 63020a203aSopenharmony_ci return EventLogCatcher::Initialize(packageName_, pid_, intParam); 64020a203aSopenharmony_ci}; 65020a203aSopenharmony_ci 66020a203aSopenharmony_ci// may block, run in another thread 67020a203aSopenharmony_ciint OpenStacktraceCatcher::Catch(int fd, int jsonFd) 68020a203aSopenharmony_ci{ 69020a203aSopenharmony_ci if (pid_ <= 0) { 70020a203aSopenharmony_ci return 0; 71020a203aSopenharmony_ci } 72020a203aSopenharmony_ci int originSize = GetFdSize(fd); 73020a203aSopenharmony_ci 74020a203aSopenharmony_ci#ifdef DUMP_STACK_IN_PROCESS 75020a203aSopenharmony_ci LogCatcherUtils::DumpStacktrace(fd, pid_); 76020a203aSopenharmony_ci#else 77020a203aSopenharmony_ci ForkAndDumpStackTrace(fd); 78020a203aSopenharmony_ci#endif 79020a203aSopenharmony_ci logSize_ = GetFdSize(fd) - originSize; 80020a203aSopenharmony_ci return logSize_; 81020a203aSopenharmony_ci} 82020a203aSopenharmony_ci 83020a203aSopenharmony_ciinline void OpenStacktraceCatcher::WaitChildPid(pid_t pid) 84020a203aSopenharmony_ci{ 85020a203aSopenharmony_ci int retryCount = 0; 86020a203aSopenharmony_ci while (retryCount < MAX_RETRY_COUNT) { 87020a203aSopenharmony_ci if (waitpid(pid, NULL, WNOHANG) != 0) { 88020a203aSopenharmony_ci break; 89020a203aSopenharmony_ci } 90020a203aSopenharmony_ci retryCount++; 91020a203aSopenharmony_ci usleep(SLEEP_TIME_US); 92020a203aSopenharmony_ci } 93020a203aSopenharmony_ci} 94020a203aSopenharmony_ci 95020a203aSopenharmony_ciint32_t OpenStacktraceCatcher::ForkAndDumpStackTrace(int32_t fd) 96020a203aSopenharmony_ci{ 97020a203aSopenharmony_ci int pid = -1; 98020a203aSopenharmony_ci int leftTimeMicroSecond = 30000000; // 30000000us 99020a203aSopenharmony_ci if ((pid = fork()) < 0) { 100020a203aSopenharmony_ci HIVIEW_LOGE("Fork error, err:%{public}d", errno); 101020a203aSopenharmony_ci return 0; 102020a203aSopenharmony_ci } 103020a203aSopenharmony_ci 104020a203aSopenharmony_ci if (pid == 0) { 105020a203aSopenharmony_ci auto newFd = dup(fd); 106020a203aSopenharmony_ci int ret = LogCatcherUtils::DumpStacktrace(newFd, pid_); 107020a203aSopenharmony_ci HIVIEW_LOGD("LogCatcherUtils::DumpStacktrace ret %{public}d", ret); 108020a203aSopenharmony_ci close(newFd); 109020a203aSopenharmony_ci _exit(ret); 110020a203aSopenharmony_ci } 111020a203aSopenharmony_ci 112020a203aSopenharmony_ci while (true) { 113020a203aSopenharmony_ci int status = 0; 114020a203aSopenharmony_ci pid_t p = waitpid(pid, &status, WNOHANG); 115020a203aSopenharmony_ci if (p < 0) { 116020a203aSopenharmony_ci HIVIEW_LOGW("Waitpid return p=%{public}d, err:%{public}d", p, errno); 117020a203aSopenharmony_ci return -1; 118020a203aSopenharmony_ci } 119020a203aSopenharmony_ci 120020a203aSopenharmony_ci if (p == pid) { 121020a203aSopenharmony_ci HIVIEW_LOGD("Dump process exited status is %{public}d", status); 122020a203aSopenharmony_ci return WEXITSTATUS(status); 123020a203aSopenharmony_ci } 124020a203aSopenharmony_ci 125020a203aSopenharmony_ci if (needStop_ || leftTimeMicroSecond <= 0) { 126020a203aSopenharmony_ci HIVIEW_LOGW("Dump stacktrace timeout, killing pid %{public}d.", pid); 127020a203aSopenharmony_ci std::string str = "Dump stacktrace timeout, Catch for " + std::to_string(pid_); 128020a203aSopenharmony_ci FileUtil::SaveStringToFd(fd, str); 129020a203aSopenharmony_ci kill(pid, SIGKILL); 130020a203aSopenharmony_ci WaitChildPid(pid); 131020a203aSopenharmony_ci return -1; 132020a203aSopenharmony_ci } 133020a203aSopenharmony_ci 134020a203aSopenharmony_ci usleep(SLEEP_TIME_US); // poll every 0.1 sec 135020a203aSopenharmony_ci leftTimeMicroSecond -= SLEEP_TIME_US; 136020a203aSopenharmony_ci } 137020a203aSopenharmony_ci} 138020a203aSopenharmony_ci} // namespace HiviewDFX 139020a203aSopenharmony_ci} // namespace OHOS 140