process exception measurement

Signed-off-by: hhl <yinhuiling@huawei.com>
This commit is contained in:
hhl 2024-11-08 19:17:09 +08:00
parent 1ab2b37fa1
commit 2630d22945
8 changed files with 175 additions and 79 deletions

View File

@ -190,4 +190,11 @@ declare_args() {
defined(global_parts_info.accesscontrol_sandbox_manager)) {
ability_runtime_feature_sandboxmanager = true
}
if (defined(global_parts_info) &&
defined(global_parts_info.hiviewdfx_hicollie)) {
app_mgr_service_hicollie_enable = true
} else {
app_mgr_service_hicollie_enable = false
}
}

View File

@ -40,6 +40,7 @@ public:
int uid;
std::string bundleName;
std::string processName;
bool isOccurException = false;
};
enum TypeAttribute {
@ -58,6 +59,7 @@ public:
int32_t pid = 0;
int state = 0;
int64_t occurTime = 0;
std::string errorName = "";
};
struct ParamInfo {
@ -79,7 +81,7 @@ public:
std::string WriteToFile(const std::string& fileName, std::string& content);
bool IsHandleAppfreeze(const std::string& bundleName);
bool IsProcessDebug(int32_t pid, std::string bundleName);
bool IsNeedIgnoreFreezeEvent(int32_t pid);
bool IsNeedIgnoreFreezeEvent(int32_t pid, const std::string& errorName);
void DeleteStack(int pid);
bool CancelAppFreezeDetect(int32_t pid, const std::string& bundleName);
void RemoveDeathProcess(std::string bundleName);
@ -100,11 +102,12 @@ private:
int NotifyANR(const FaultData& faultData, const AppfreezeManager::AppInfo& appInfo,
const std::string& binderInfo, const std::string& memoryContent);
int64_t GetFreezeCurrentTime();
void SetFreezeState(int32_t pid, int state);
void SetFreezeState(int32_t pid, int state, const std::string& errorName);
int GetFreezeState(int32_t pid);
int64_t GetFreezeTime(int32_t pid);
void ClearOldInfo();
void CollectFreezeSysMemory(std::string& memoryContent);
int MergeNotifyInfo(FaultData& faultNotifyData, const AppfreezeManager::AppInfo& appInfo);
static const inline std::string LOGGER_DEBUG_PROC_PATH = "/proc/transaction_proc";
std::string name_;

View File

@ -141,6 +141,40 @@ void AppfreezeManager::CollectFreezeSysMemory(std::string& memoryContent)
memoryContent += tmp;
}
int AppfreezeManager::MergeNotifyInfo(FaultData& faultNotifyData, const AppfreezeManager::AppInfo& appInfo)
{
std::string memoryContent = "";
CollectFreezeSysMemory(memoryContent);
std::string fileName = faultNotifyData.errorObject.name + "_" +
AbilityRuntime::TimeUtil::FormatTime("%Y%m%d%H%M%S") + "_" + std::to_string(appInfo.pid) + "_stack";
std::string catcherStack = "";
std::string catchJsonStack = "";
std::string fullStackPath = "";
if (faultNotifyData.errorObject.name == AppFreezeType::LIFECYCLE_HALF_TIMEOUT
|| faultNotifyData.errorObject.name == AppFreezeType::LIFECYCLE_TIMEOUT) {
catcherStack += CatcherStacktrace(appInfo.pid);
fullStackPath = WriteToFile(fileName, catcherStack);
faultNotifyData.errorObject.stack = fullStackPath;
} else {
auto start = GetMilliseconds();
std::string timeStamp = "\nTimestamp:" + AbilityRuntime::TimeUtil::FormatTime("%Y-%m-%d %H:%M:%S") +
":" + std::to_string(start % SEC_TO_MILLISEC);
faultNotifyData.errorObject.message += timeStamp;
catchJsonStack += CatchJsonStacktrace(appInfo.pid, faultNotifyData.errorObject.name);
fullStackPath = WriteToFile(fileName, catchJsonStack);
faultNotifyData.errorObject.stack = fullStackPath;
}
if (appInfo.isOccurException) {
faultNotifyData.errorObject.message += "\nnotifyAppFault exception.\n";
}
if (faultNotifyData.errorObject.name == AppFreezeType::APP_INPUT_BLOCK) {
AcquireStack(faultNotifyData, appInfo, memoryContent);
} else {
NotifyANR(faultNotifyData, appInfo, "", memoryContent);
}
return 0;
}
int AppfreezeManager::AppfreezeHandleWithStack(const FaultData& faultData, const AppfreezeManager::AppInfo& appInfo)
{
TAG_LOGD(AAFwkTag::APPDFR, "called %{public}s, bundleName %{public}s, name_ %{public}s",
@ -157,42 +191,7 @@ int AppfreezeManager::AppfreezeHandleWithStack(const FaultData& faultData, const
HITRACE_METER_FMT(HITRACE_TAG_APP, "AppfreezeHandleWithStack pid:%d-name:%s",
appInfo.pid, faultData.errorObject.name.c_str());
if (faultData.errorObject.name == AppFreezeType::LIFECYCLE_TIMEOUT
|| faultData.errorObject.name == AppFreezeType::APP_INPUT_BLOCK
|| faultData.errorObject.name == AppFreezeType::THREAD_BLOCK_6S) {
if (AppExecFwk::AppfreezeManager::GetInstance()->IsNeedIgnoreFreezeEvent(appInfo.pid)) {
TAG_LOGE(AAFwkTag::APPDFR, "appFreeze happend");
return 0;
}
}
std::string memoryContent = "";
CollectFreezeSysMemory(memoryContent);
std::string fileName = faultData.errorObject.name + "_" +
AbilityRuntime::TimeUtil::FormatTime("%Y%m%d%H%M%S") + "_" + std::to_string(appInfo.pid) + "_stack";
std::string catcherStack = "";
std::string catchJsonStack = "";
std::string fullStackPath = "";
if (faultData.errorObject.name == AppFreezeType::LIFECYCLE_HALF_TIMEOUT
|| faultData.errorObject.name == AppFreezeType::LIFECYCLE_TIMEOUT) {
catcherStack += CatcherStacktrace(appInfo.pid);
fullStackPath = WriteToFile(fileName, catcherStack);
faultNotifyData.errorObject.stack = fullStackPath;
} else {
auto start = GetMilliseconds();
std::string timeStamp = "\nTimestamp:" + AbilityRuntime::TimeUtil::FormatTime("%Y-%m-%d %H:%M:%S") +
":" + std::to_string(start % SEC_TO_MILLISEC);
faultNotifyData.errorObject.message += timeStamp;
catchJsonStack += CatchJsonStacktrace(appInfo.pid, faultData.errorObject.name);
fullStackPath = WriteToFile(fileName, catchJsonStack);
faultNotifyData.errorObject.stack = fullStackPath;
}
if (faultNotifyData.errorObject.name == AppFreezeType::APP_INPUT_BLOCK) {
AcquireStack(faultNotifyData, appInfo, memoryContent);
} else {
NotifyANR(faultNotifyData, appInfo, "", memoryContent);
}
return 0;
return MergeNotifyInfo(faultNotifyData, appInfo);
}
std::string AppfreezeManager::WriteToFile(const std::string& fileName, std::string& content)
@ -518,7 +517,7 @@ int64_t AppfreezeManager::GetFreezeCurrentTime()
return static_cast<int64_t>(((t.tv_sec) * NANOSECONDS + t.tv_nsec) / MICROSECONDS);
}
void AppfreezeManager::SetFreezeState(int32_t pid, int state)
void AppfreezeManager::SetFreezeState(int32_t pid, int state, const std::string& errorName)
{
std::lock_guard<ffrt::mutex> lock(freezeMutex_);
if (appfreezeInfo_.find(pid) != appfreezeInfo_.end()) {
@ -529,6 +528,7 @@ void AppfreezeManager::SetFreezeState(int32_t pid, int state)
info.pid = pid;
info.state = state;
info.occurTime = GetFreezeCurrentTime();
info.errorName = errorName;
appfreezeInfo_.emplace(pid, info);
}
}
@ -567,7 +567,7 @@ void AppfreezeManager::ClearOldInfo()
}
}
bool AppfreezeManager::IsNeedIgnoreFreezeEvent(int32_t pid)
bool AppfreezeManager::IsNeedIgnoreFreezeEvent(int32_t pid, const std::string& errorName)
{
if (appfreezeInfo_.size() >= FREEZEMAP_SIZE_MAX) {
ClearOldInfo();
@ -584,12 +584,15 @@ bool AppfreezeManager::IsNeedIgnoreFreezeEvent(int32_t pid)
}
return true;
} else {
if (errorName == "THREAD_BLOCK_3S") {
return false;
}
if (currentTime > FREEZE_TIME_LIMIT && diff < FREEZE_TIME_LIMIT) {
return true;
}
SetFreezeState(pid, AppFreezeState::APPFREEZE_STATE_FREEZE);
TAG_LOGI(AAFwkTag::APPDFR, "durationTime: "
"%{public}" PRId64 " SetFreezeState: %{public}d", diff, state);
SetFreezeState(pid, AppFreezeState::APPFREEZE_STATE_FREEZE, errorName);
TAG_LOGI(AAFwkTag::APPDFR, "durationTime: %{public}" PRId64 ", SetFreezeState: "
"%{public}s", diff, errorName.c_str());
return false;
}
}

View File

@ -178,6 +178,9 @@ ohos_shared_library("libappms") {
if (ability_runtime_app_no_response_dialog) {
defines += [ "APP_NO_RESPONSE_DIALOG" ]
}
if (app_mgr_service_hicollie_enable) {
defines += [ "APP_MGR_SERVICE_HICOLLIE_ENABLE" ]
}
cflags += [ "-DAPP_NO_RESPONSE_BUNDLENAME=\"${ability_runtime_app_no_response_bundlename}\"" ]
version_script = "libappms.map"

View File

@ -1843,6 +1843,12 @@ private:
int32_t KillProcessByPidInner(const pid_t pid, const std::string& reason,
const std::string& killReason, std::shared_ptr<AppRunningRecord> appRecord);
bool IsAllowedNWebPreload(const std::string &processName);
void ParseInfoToAppfreeze(const FaultData &faultData, int32_t pid, int32_t uid, const std::string &bundleName,
const std::string &processName, const bool isOccurException = false);
int GetExceptionTimerId(const FaultData &faultData, const std::string &bundleName,
const std::shared_ptr<AppRunningRecord> &appRecord, const int32_t pid, const int32_t callerUid);
int32_t SubmitDfxFaultTask(const FaultData &faultData, const std::string &bundleName,
const std::shared_ptr<AppRunningRecord> &appRecord, const int32_t pid);
const std::string TASK_ON_CALLBACK_DIED = "OnCallbackDiedTask";
std::vector<AppStateCallbackWithUserId> appStateCallbacks_;
std::shared_ptr<RemoteClientManager> remoteClientManager_;

View File

@ -96,6 +96,10 @@
#include "fault_data.h"
#include "modal_system_app_freeze_uiextension.h"
#endif
#ifdef APP_MGR_SERVICE_HICOLLIE_ENABLE
#include "xcollie/xcollie.h"
#include "xcollie/xcollie_define.h"
#endif
namespace OHOS {
namespace AppExecFwk {
@ -5912,10 +5916,96 @@ void AppMgrServiceInner::AppRecoveryNotifyApp(int32_t pid, const std::string& bu
taskHandler_->SubmitTask(waitSaveTask, timeOutName, timeOut);
}
void AppMgrServiceInner::ParseInfoToAppfreeze(const FaultData &faultData, int32_t pid, int32_t uid,
const std::string &bundleName, const std::string &processName, const bool isOccurException)
{
if (faultData.faultType == FaultDataType::APP_FREEZE) {
AppfreezeManager::AppInfo info = {
.pid = pid,
.uid = uid,
.bundleName = bundleName,
.processName = processName,
.isOccurException = isOccurException,
};
AppExecFwk::AppfreezeManager::GetInstance()->AppfreezeHandleWithStack(faultData, info);
}
TAG_LOGW(AAFwkTag::APPMGR,
"name: %{public}s, faultType: %{public}d, uid: %{public}d, pid: %{public}d, bundleName: %{public}s,"
" processName: %{public}s, faultData.forceExit:%{public}d, faultData.waitSaveState:%{public}d,"
" isOccurException:%{public}d",
faultData.errorObject.name.c_str(), faultData.faultType, uid, pid, bundleName.c_str(),
processName.c_str(), faultData.forceExit, faultData.waitSaveState, isOccurException);
}
int AppMgrServiceInner::GetExceptionTimerId(const FaultData &faultData, const std::string &bundleName,
const std::shared_ptr<AppRunningRecord> &appRecord, const int32_t pid, const int32_t callerUid)
{
auto exceptionCallback = [faultData, bundleName, appRecord, pid, callerUid,
innerService = shared_from_this()](void *) {
auto threadTask = [faultData, bundleName, appRecord, pid, callerUid, innerService]() {
if (innerService->CheckAppFault(appRecord, faultData)) {
TAG_LOGI(AAFwkTag::APPMGR, "current dfx task is working.");
return;
}
bool isOccurException = true;
innerService->ParseInfoToAppfreeze(faultData, pid, callerUid, bundleName, appRecord->GetProcessName(),
isOccurException);
if (faultData.errorObject.name != AppFreezeType::THREAD_BLOCK_3S ||
faultData.errorObject.name != AppFreezeType::LIFECYCLE_HALF_TIMEOUT) {
TAG_LOGI(AAFwkTag::APPMGR, "faultData: %{public}s,pid: %{public}d will exit because %{public}s",
bundleName.c_str(), pid, innerService->FaultTypeToString(faultData.faultType).c_str());
innerService->KillProcessByPid(pid, faultData.errorObject.name);
return;
}
};
std::thread dfxThread(threadTask);
if (dfxThread.joinable()) {
dfxThread.join();
}
};
constexpr uint32_t timeout = 15; // 15s
int exceptionId = -1;
#ifdef APP_MGR_SERVICE_HICOLLIE_ENABLE
exceptionId = HiviewDFX::XCollie::GetInstance().SetTimer("DfxFault::Exception", timeout,
exceptionCallback, nullptr, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY);
#endif
return exceptionId;
}
int32_t AppMgrServiceInner::SubmitDfxFaultTask(const FaultData &faultData, const std::string &bundleName,
const std::shared_ptr<AppRunningRecord> &appRecord, const int32_t pid)
{
int32_t callerUid = IPCSkeleton::GetCallingUid();
std::string processName = appRecord->GetProcessName();
int exceptionId = GetExceptionTimerId(faultData, bundleName, appRecord, pid, callerUid);
auto notifyAppTask = [appRecord, pid, callerUid, bundleName, processName, faultData, exceptionId,
innerService = shared_from_this()]() {
innerService->ParseInfoToAppfreeze(faultData, pid, callerUid, bundleName, processName);
#ifdef APP_MGR_SERVICE_HICOLLIE_ENABLE
HiviewDFX::XCollie::GetInstance().CancelTimer(exceptionId);
#endif
};
if (!dfxTaskHandler_) {
TAG_LOGW(AAFwkTag::APPMGR, "get dfx handler fail");
return ERR_INVALID_VALUE;
}
dfxTaskHandler_->SubmitTask(notifyAppTask, "NotifyAppFaultTask");
constexpr int delayTime = 15 * 1000; // 15s
auto task = [pid, innerService = shared_from_this()]() {
AppExecFwk::AppfreezeManager::GetInstance()->DeleteStack(pid);
};
dfxTaskHandler_->SubmitTask(task, "DeleteStack", delayTime);
return ERR_OK;
}
int32_t AppMgrServiceInner::NotifyAppFault(const FaultData &faultData)
{
TAG_LOGI(AAFwkTag::APPMGR, "call");
int32_t callerUid = IPCSkeleton::GetCallingUid();
int32_t pid = IPCSkeleton::GetCallingPid();
auto appRecord = GetAppRunningRecordByPid(pid);
if (appRecord == nullptr) {
@ -5928,7 +6018,6 @@ int32_t AppMgrServiceInner::NotifyAppFault(const FaultData &faultData)
return ERR_OK;
}
std::string bundleName = appRecord->GetBundleName();
std::string processName = appRecord->GetProcessName();
if (AppExecFwk::AppfreezeManager::GetInstance()->IsProcessDebug(pid, bundleName)) {
TAG_LOGW(AAFwkTag::APPMGR,
"don't report event and kill:%{public}s, pid:%{public}d, bundleName:%{public}s",
@ -5945,38 +6034,19 @@ int32_t AppMgrServiceInner::NotifyAppFault(const FaultData &faultData)
AppRecoveryNotifyApp(pid, bundleName, FaultDataType::APP_FREEZE, "recoveryTimeout");
}
}
auto notifyAppTask = [appRecord, pid, callerUid, bundleName, processName, faultData,
innerService = shared_from_this()]() {
if (faultData.faultType == FaultDataType::APP_FREEZE) {
AppfreezeManager::AppInfo info = {
.pid = pid,
.uid = callerUid,
.bundleName = bundleName,
.processName = processName,
};
AppExecFwk::AppfreezeManager::GetInstance()->AppfreezeHandleWithStack(faultData, info);
if (faultData.errorObject.name == AppFreezeType::LIFECYCLE_TIMEOUT ||
faultData.errorObject.name == AppFreezeType::APP_INPUT_BLOCK ||
faultData.errorObject.name == AppFreezeType::THREAD_BLOCK_6S ||
faultData.errorObject.name == AppFreezeType::THREAD_BLOCK_3S) {
if (AppExecFwk::AppfreezeManager::GetInstance()->IsNeedIgnoreFreezeEvent(pid, faultData.errorObject.name)) {
TAG_LOGE(AAFwkTag::APPDFR, "appFreeze happend");
return ERR_OK;
}
TAG_LOGW(AAFwkTag::APPMGR,
"name: %{public}s, faultType: %{public}d, uid: %{public}d, pid: %{public}d, bundleName: %{public}s,"
" processName: %{public}s, faultData.forceExit:%{public}d, faultData.waitSaveState:%{public}d",
faultData.errorObject.name.c_str(), faultData.faultType, callerUid, pid, bundleName.c_str(),
processName.c_str(), faultData.forceExit, faultData.waitSaveState);
};
if (!dfxTaskHandler_) {
TAG_LOGW(AAFwkTag::APPMGR, "get dfx handler fail");
}
if (SubmitDfxFaultTask(faultData, bundleName, appRecord, pid) != ERR_OK) {
return ERR_INVALID_VALUE;
}
dfxTaskHandler_->SubmitTask(notifyAppTask, "NotifyAppFaultTask");
constexpr int delayTime = 15 * 1000; // 15s
auto task = [pid, innerService = shared_from_this()]() {
AppExecFwk::AppfreezeManager::GetInstance()->DeleteStack(pid);
};
dfxTaskHandler_->SubmitTask(task, "DeleteStack", delayTime);
if (appRecord->GetApplicationInfo()->asanEnabled) {
TAG_LOGI(AAFwkTag::APPMGR,
"faultData: %{public}s, pid: %{public}d", bundleName.c_str(), pid);

View File

@ -65,7 +65,8 @@ bool DoSomethingInterestingWithMyAPI(const char* data, size_t size)
int32_t pid = static_cast<int32_t>(GetU32Data(data));
std::string processName(data, size);
freeze->IsProcessDebug(pid, processName);
freeze->IsNeedIgnoreFreezeEvent(pid);
std::string errorName(data, size);
freeze->IsNeedIgnoreFreezeEvent(pid, errorName);
freeze->CancelAppFreezeDetect(pid, bundleName);
freeze->ResetAppfreezeState(pid, bundleName);
freeze->IsValidFreezeFilter(pid, bundleName);
@ -81,7 +82,7 @@ bool DoSomethingInterestingWithMyAPI(const char* data, size_t size)
std::string binderInfo(data, size);
freeze->NotifyANR(faultData, appInfo, binderInfo, memoryContent);
int state = static_cast<int>(GetU32Data(data));
freeze->SetFreezeState(pid, state);
freeze->SetFreezeState(pid, state, errorName);
freeze->GetFreezeState(pid);
freeze->GetFreezeTime(pid);
return true;

View File

@ -195,13 +195,16 @@ HWTEST_F(AppfreezeManagerTest, AppfreezeManagerTest_006, TestSize.Level1)
appfreezeManager->ClearOldInfo();
int32_t pid = static_cast<int32_t>(getprocpid());
int state = AppfreezeManager::AppFreezeState::APPFREEZE_STATE_FREEZE;
bool result = appfreezeManager->IsNeedIgnoreFreezeEvent(pid);
bool result = appfreezeManager->IsNeedIgnoreFreezeEvent(pid, "Test");
EXPECT_TRUE(!result);
appfreezeManager->ClearOldInfo();
result = appfreezeManager->IsProcessDebug(pid, "Test");
EXPECT_TRUE(!result);
result = appfreezeManager->IsNeedIgnoreFreezeEvent(pid);
result = appfreezeManager->IsNeedIgnoreFreezeEvent(pid, "Test");
EXPECT_TRUE(result);
std::string errorName = "THREAD_BLOCK_3S";
result = appfreezeManager->IsNeedIgnoreFreezeEvent(12000, errorName);
EXPECT_TRUE(!result);
}
/**
@ -215,8 +218,8 @@ HWTEST_F(AppfreezeManagerTest, AppfreezeManagerTest_007, TestSize.Level1)
int state = AppfreezeManager::AppFreezeState::APPFREEZE_STATE_IDLE;
EXPECT_EQ(appfreezeManager->GetFreezeState(pid), state);
appfreezeManager->SetFreezeState(pid,
AppfreezeManager::AppFreezeState::APPFREEZE_STATE_FREEZE);
appfreezeManager->SetFreezeState(pid, state);
AppfreezeManager::AppFreezeState::APPFREEZE_STATE_FREEZE, "Test");
appfreezeManager->SetFreezeState(pid, state, "Test");
EXPECT_EQ(appfreezeManager->GetFreezeState(pid), state);
}