1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 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_sigdump_handler.h" 17800b99b8Sopenharmony_ci 18800b99b8Sopenharmony_ci#include <cinttypes> 19800b99b8Sopenharmony_ci#include <csignal> 20800b99b8Sopenharmony_ci#include <ctime> 21800b99b8Sopenharmony_ci#include <mutex> 22800b99b8Sopenharmony_ci#include <sigchain.h> 23800b99b8Sopenharmony_ci#include <sys/syscall.h> 24800b99b8Sopenharmony_ci#include <thread> 25800b99b8Sopenharmony_ci#include <unistd.h> 26800b99b8Sopenharmony_ci 27800b99b8Sopenharmony_ci#include "backtrace_local.h" 28800b99b8Sopenharmony_ci#include "dfx_define.h" 29800b99b8Sopenharmony_ci#include "dfx_dump_res.h" 30800b99b8Sopenharmony_ci#include "dfx_log.h" 31800b99b8Sopenharmony_ci#include "faultloggerd_client.h" 32800b99b8Sopenharmony_ci 33800b99b8Sopenharmony_cinamespace OHOS { 34800b99b8Sopenharmony_cinamespace HiviewDFX { 35800b99b8Sopenharmony_cinamespace { 36800b99b8Sopenharmony_ci#ifdef LOG_DOMAIN 37800b99b8Sopenharmony_ci#undef LOG_DOMAIN 38800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11 39800b99b8Sopenharmony_ci#endif 40800b99b8Sopenharmony_ci 41800b99b8Sopenharmony_ci#ifdef LOG_TAG 42800b99b8Sopenharmony_ci#undef LOG_TAG 43800b99b8Sopenharmony_ci#define LOG_TAG "DfxSigDumpHandler" 44800b99b8Sopenharmony_ci#endif 45800b99b8Sopenharmony_ci} 46800b99b8Sopenharmony_ci 47800b99b8Sopenharmony_cistatic const struct timespec SIG_WAIT_TIMEOUT = { 48800b99b8Sopenharmony_ci .tv_sec = 1, 49800b99b8Sopenharmony_ci .tv_nsec = 0, 50800b99b8Sopenharmony_ci}; 51800b99b8Sopenharmony_ci 52800b99b8Sopenharmony_ciclass DfxSigDumpHandler { 53800b99b8Sopenharmony_cipublic: 54800b99b8Sopenharmony_ci static DfxSigDumpHandler& GetInstance(void); 55800b99b8Sopenharmony_ci bool Init(void); 56800b99b8Sopenharmony_ci void Deinit(void); 57800b99b8Sopenharmony_ci bool IsThreadRunning(void) const; 58800b99b8Sopenharmony_ci int GetRunThreadId(void) const; 59800b99b8Sopenharmony_ci void SetRunThreadId(int tid); 60800b99b8Sopenharmony_ciprivate: 61800b99b8Sopenharmony_ci DfxSigDumpHandler() = default; 62800b99b8Sopenharmony_ci DfxSigDumpHandler(DfxSigDumpHandler&) = delete; 63800b99b8Sopenharmony_ci DfxSigDumpHandler& operator=(const DfxSigDumpHandler&)=delete; 64800b99b8Sopenharmony_ci static void RunThread(void); 65800b99b8Sopenharmony_ci static void SignalDumpRetranHandler(int signo, siginfo_t* si, void* context); 66800b99b8Sopenharmony_ci bool isThreadRunning_{false}; 67800b99b8Sopenharmony_ci int runThreadId_{0}; 68800b99b8Sopenharmony_ci}; 69800b99b8Sopenharmony_ci 70800b99b8Sopenharmony_ciDfxSigDumpHandler& DfxSigDumpHandler::GetInstance() 71800b99b8Sopenharmony_ci{ 72800b99b8Sopenharmony_ci static DfxSigDumpHandler sigDumperHandler; 73800b99b8Sopenharmony_ci return sigDumperHandler; 74800b99b8Sopenharmony_ci} 75800b99b8Sopenharmony_ci 76800b99b8Sopenharmony_cibool DfxSigDumpHandler::IsThreadRunning() const 77800b99b8Sopenharmony_ci{ 78800b99b8Sopenharmony_ci return isThreadRunning_; 79800b99b8Sopenharmony_ci} 80800b99b8Sopenharmony_ci 81800b99b8Sopenharmony_ciint DfxSigDumpHandler::GetRunThreadId() const 82800b99b8Sopenharmony_ci{ 83800b99b8Sopenharmony_ci return runThreadId_; 84800b99b8Sopenharmony_ci} 85800b99b8Sopenharmony_ci 86800b99b8Sopenharmony_civoid DfxSigDumpHandler::SetRunThreadId(int tid) 87800b99b8Sopenharmony_ci{ 88800b99b8Sopenharmony_ci runThreadId_ = tid; 89800b99b8Sopenharmony_ci} 90800b99b8Sopenharmony_ci 91800b99b8Sopenharmony_civoid DfxSigDumpHandler::SignalDumpRetranHandler(int signo, siginfo_t* si, void* context) 92800b99b8Sopenharmony_ci{ 93800b99b8Sopenharmony_ci int tid = DfxSigDumpHandler::GetInstance().GetRunThreadId(); 94800b99b8Sopenharmony_ci if (tid == 0) { 95800b99b8Sopenharmony_ci return; 96800b99b8Sopenharmony_ci } 97800b99b8Sopenharmony_ci if (syscall(SYS_tkill, tid, SIGDUMP) != 0) { 98800b99b8Sopenharmony_ci return; 99800b99b8Sopenharmony_ci } 100800b99b8Sopenharmony_ci} 101800b99b8Sopenharmony_ci 102800b99b8Sopenharmony_civoid DfxSigDumpHandler::RunThread() 103800b99b8Sopenharmony_ci{ 104800b99b8Sopenharmony_ci sigset_t set; 105800b99b8Sopenharmony_ci sigemptyset(&set); 106800b99b8Sopenharmony_ci sigaddset(&set, SIGDUMP); 107800b99b8Sopenharmony_ci if (pthread_sigmask(SIG_BLOCK, &set, nullptr) != 0) { 108800b99b8Sopenharmony_ci DFXLOGE("pthread sigmask failed, err(%{public}d)", errno); 109800b99b8Sopenharmony_ci } 110800b99b8Sopenharmony_ci DfxSigDumpHandler::GetInstance().SetRunThreadId(gettid()); 111800b99b8Sopenharmony_ci while (DfxSigDumpHandler::GetInstance().IsThreadRunning()) { 112800b99b8Sopenharmony_ci siginfo_t si; 113800b99b8Sopenharmony_ci if (OHOS_TEMP_FAILURE_RETRY(sigtimedwait(&set, &si, &SIG_WAIT_TIMEOUT)) == -1) { 114800b99b8Sopenharmony_ci continue; 115800b99b8Sopenharmony_ci } 116800b99b8Sopenharmony_ci int32_t resFd = -1; 117800b99b8Sopenharmony_ci int res = DUMP_ESUCCESS; 118800b99b8Sopenharmony_ci int32_t pid = getpid(); 119800b99b8Sopenharmony_ci FaultLoggerPipeType jsonType = FaultLoggerPipeType::PIPE_FD_JSON_WRITE_RES; 120800b99b8Sopenharmony_ci int32_t fd = RequestPipeFd(pid, FaultLoggerPipeType::PIPE_FD_JSON_WRITE_BUF); 121800b99b8Sopenharmony_ci if (fd < 0) { 122800b99b8Sopenharmony_ci fd = RequestPipeFd(pid, FaultLoggerPipeType::PIPE_FD_WRITE_BUF); 123800b99b8Sopenharmony_ci jsonType = FaultLoggerPipeType::PIPE_FD_WRITE_RES; 124800b99b8Sopenharmony_ci } 125800b99b8Sopenharmony_ci if (fd < 0) { 126800b99b8Sopenharmony_ci DFXLOGE("Pid %{public}d GetPipeFd Failed", pid); 127800b99b8Sopenharmony_ci continue; 128800b99b8Sopenharmony_ci } 129800b99b8Sopenharmony_ci resFd = RequestPipeFd(pid, jsonType); 130800b99b8Sopenharmony_ci if (resFd < 0) { 131800b99b8Sopenharmony_ci DFXLOGE("Pid %{public}d GetPipeResFd Failed", pid); 132800b99b8Sopenharmony_ci close(fd); 133800b99b8Sopenharmony_ci continue; 134800b99b8Sopenharmony_ci } 135800b99b8Sopenharmony_ci std::string dumpInfo = OHOS::HiviewDFX::GetProcessStacktrace(); 136800b99b8Sopenharmony_ci const ssize_t nwrite = static_cast<ssize_t>(dumpInfo.length()); 137800b99b8Sopenharmony_ci if (!dumpInfo.empty() && 138800b99b8Sopenharmony_ci OHOS_TEMP_FAILURE_RETRY(write(fd, dumpInfo.data(), dumpInfo.length())) != nwrite) { 139800b99b8Sopenharmony_ci DFXLOGE("Pid %{public}d Write Buf Pipe Failed(%{public}d), nwrite(%{public}zd)", pid, errno, nwrite); 140800b99b8Sopenharmony_ci res = DUMP_EBADFRAME; 141800b99b8Sopenharmony_ci } else if (dumpInfo.empty()) { 142800b99b8Sopenharmony_ci res = DUMP_ENOINFO; 143800b99b8Sopenharmony_ci } 144800b99b8Sopenharmony_ci ssize_t nres = OHOS_TEMP_FAILURE_RETRY(write(resFd, &res, sizeof(res))); 145800b99b8Sopenharmony_ci if (nres != sizeof(res)) { 146800b99b8Sopenharmony_ci DFXLOGE("Pid %{public}d Write Res Pipe Failed(%{public}d), nres(%{public}zd)", pid, errno, nres); 147800b99b8Sopenharmony_ci } 148800b99b8Sopenharmony_ci close(fd); 149800b99b8Sopenharmony_ci close(resFd); 150800b99b8Sopenharmony_ci } 151800b99b8Sopenharmony_ci} 152800b99b8Sopenharmony_ci 153800b99b8Sopenharmony_cibool DfxSigDumpHandler::Init() 154800b99b8Sopenharmony_ci{ 155800b99b8Sopenharmony_ci if (IsThreadRunning()) { 156800b99b8Sopenharmony_ci DFXLOGI("SigDumpHandler Thread has been inited"); 157800b99b8Sopenharmony_ci return true; 158800b99b8Sopenharmony_ci } 159800b99b8Sopenharmony_ci remove_all_special_handler(SIGDUMP); 160800b99b8Sopenharmony_ci struct sigaction action; 161800b99b8Sopenharmony_ci (void)memset_s(&action, sizeof(action), 0, sizeof(action)); 162800b99b8Sopenharmony_ci sigemptyset(&action.sa_mask); 163800b99b8Sopenharmony_ci sigaddset(&action.sa_mask, SIGDUMP); 164800b99b8Sopenharmony_ci action.sa_flags = SA_RESTART | SA_SIGINFO; 165800b99b8Sopenharmony_ci action.sa_sigaction = DfxSigDumpHandler::SignalDumpRetranHandler; 166800b99b8Sopenharmony_ci DFXLOGI("Init Install signal handler"); 167800b99b8Sopenharmony_ci sigaction(SIGDUMP, &action, nullptr); 168800b99b8Sopenharmony_ci isThreadRunning_ = true; 169800b99b8Sopenharmony_ci std::thread catchThread = std::thread(&DfxSigDumpHandler::RunThread); 170800b99b8Sopenharmony_ci catchThread.detach(); 171800b99b8Sopenharmony_ci return true; 172800b99b8Sopenharmony_ci} 173800b99b8Sopenharmony_ci 174800b99b8Sopenharmony_civoid DfxSigDumpHandler::Deinit() 175800b99b8Sopenharmony_ci{ 176800b99b8Sopenharmony_ci isThreadRunning_ = false; 177800b99b8Sopenharmony_ci} 178800b99b8Sopenharmony_ci} // namespace HiviewDFX 179800b99b8Sopenharmony_ci} // namespace OHOS 180800b99b8Sopenharmony_ci 181800b99b8Sopenharmony_cibool InitSigDumpHandler() 182800b99b8Sopenharmony_ci{ 183800b99b8Sopenharmony_ci return OHOS::HiviewDFX::DfxSigDumpHandler::GetInstance().Init(); 184800b99b8Sopenharmony_ci} 185800b99b8Sopenharmony_ci 186800b99b8Sopenharmony_civoid DeinitSigDumpHandler() 187800b99b8Sopenharmony_ci{ 188800b99b8Sopenharmony_ci OHOS::HiviewDFX::DfxSigDumpHandler::GetInstance().Deinit(); 189800b99b8Sopenharmony_ci} 190