diff --git a/services/init/include/init_service.h b/services/init/include/init_service.h index 48059cfac4b68e35ebfebd27dbfbb3c2215117f2..d6081605f063bfc196ec1043579920a45d656329 100755 --- a/services/init/include/init_service.h +++ b/services/init/include/init_service.h @@ -79,6 +79,8 @@ typedef struct { int pid; int crashCnt; time_t firstCrashTime; + int crashCount; + int crashTime; unsigned int attribute; int importance; Perms servPerm; diff --git a/services/init/init_common_service.c b/services/init/init_common_service.c index 6fe73aeb6924d9e7d19e2633488a837323ae5fd7..b2b33fb87bb6086c8e5d29456b3917ad9629ad47 100755 --- a/services/init/init_common_service.c +++ b/services/init/init_common_service.c @@ -47,14 +47,9 @@ #define TIOCSCTTY 0x540E #endif // 240 seconds, 4 minutes -static const int CRASH_TIME_LIMIT = 240; -// maximum number of crashes within time CRASH_TIME_LIMIT for one service -static const int CRASH_COUNT_LIMIT = 4; - -// 240 seconds, 4 minutes -static const int CRITICAL_CRASH_TIME_LIMIT = 240; -// maximum number of crashes within time CRITICAL_CRASH_TIME_LIMIT for one service -static const int CRITICAL_CRASH_COUNT_LIMIT = 4; +static const int DEFAULT_CRASH_TIME = 240; +// maximum number of crashes within time DEFAULT_CRASH_TIME for one service +static const int DEFAULT_CRASH_COUNT = 4; static int SetAllAmbientCapability(void) { @@ -331,14 +326,14 @@ void ServiceReap(Service *service) } if (service->attribute & SERVICE_ATTR_CRITICAL) { // critical - if (CalculateCrashTime(service, CRITICAL_CRASH_TIME_LIMIT, CRITICAL_CRASH_COUNT_LIMIT) == false) { + if (CalculateCrashTime(service, service->crashTime, service->crashCount) == false) { INIT_LOGE("Critical service \" %s \" crashed %d times, rebooting system", - service->name, CRITICAL_CRASH_COUNT_LIMIT); + service->name, service->crashCount); ExecReboot("reboot"); } } else if (!(service->attribute & SERVICE_ATTR_NEED_RESTART)) { - if (CalculateCrashTime(service, CRASH_TIME_LIMIT, CRASH_COUNT_LIMIT) == false) { - INIT_LOGE("Service name=%s, crash %d times, no more start.", service->name, CRASH_COUNT_LIMIT); + if (CalculateCrashTime(service, DEFAULT_CRASH_TIME, DEFAULT_CRASH_COUNT) == false) { + INIT_LOGE("Service name=%s, crash %d times, no more start.", service->name, DEFAULT_CRASH_COUNT); return; } } diff --git a/services/init/init_service_manager.c b/services/init/init_service_manager.c index 295ae08b1d407e04e09014fc61d6c21010544a21..41df194a6ffb2b8e00afad3eca7b9e43daaa71e5 100755 --- a/services/init/init_service_manager.c +++ b/services/init/init_service_manager.c @@ -34,6 +34,10 @@ // All serivce processes that init will fork+exec. static ServiceSpace g_serviceSpace = { { &g_serviceSpace.services, &g_serviceSpace.services }, 0 }; +static const int CRITICAL_DEFAULT_CRASH_TIME = 20; +// maximum number of crashes within time CRITICAL_DEFAULT_CRASH_TIME for one service +static const int CRITICAL_DEFAULT_CRASH_COUNT = 4; +static const int CRITICAL_CONFIG_ARRAY_LEN = 3; #ifdef OHOS_SERVICE_DUMP static void DumpServiceArgs(const char *info, const ServiceArgs *args) @@ -516,6 +520,59 @@ static int CheckServiceKeyName(const cJSON *curService) return SERVICE_SUCCESS; } +int GetCritical(const cJSON *curArrItem, Service *curServ, const char *attrName, int flag) +{ + int criticalSize = 0; + curServ->crashCount = CRITICAL_DEFAULT_CRASH_COUNT; + curServ->crashTime = CRITICAL_DEFAULT_CRASH_TIME; + cJSON *arrItem = cJSON_GetObjectItem(curArrItem, attrName); + if (arrItem == NULL) { + return SERVICE_SUCCESS; + } + + if (cJSON_IsNumber(arrItem)) { + return GetServiceAttr(curArrItem, curServ, attrName, flag, NULL); + } else if (cJSON_IsArray(arrItem)) { + criticalSize = cJSON_GetArraySize(arrItem); + cJSON *attrItem = cJSON_GetArrayItem(arrItem, 0); // 0 : critical attribute index + if (attrItem == NULL || !cJSON_IsNumber(attrItem)) { + INIT_LOGE("%s critical invalid", curServ->name); + return SERVICE_FAILURE; + } + int attrValue = (int)cJSON_GetNumberValue(attrItem); + curServ->attribute &= ~flag; + if (criticalSize == 1) { + if (attrValue == 1) { + curServ->attribute |= flag; + } + } else if (criticalSize == CRITICAL_CONFIG_ARRAY_LEN) { + cJSON *crashCountItem = cJSON_GetArrayItem(arrItem, 1); // 1 : critical crash count index + INIT_ERROR_CHECK(crashCountItem != NULL, return SERVICE_FAILURE, "%s critical invalid", curServ->name); + int value = (int)cJSON_GetNumberValue(crashCountItem); + INIT_ERROR_CHECK(value > 0, return SERVICE_FAILURE, "%s critical crashc ount invalid", curServ->name); + curServ->crashCount = value; + + cJSON *crashTimeItem = cJSON_GetArrayItem(arrItem, 2); // 2 : critical crash time index + INIT_ERROR_CHECK(crashTimeItem != NULL, return SERVICE_FAILURE, "%s critical invalid", curServ->name); + value = (int)cJSON_GetNumberValue(crashTimeItem); + INIT_ERROR_CHECK(value > 0, return SERVICE_FAILURE, "%s critical crash time invalid", curServ->name); + curServ->crashTime = value; + + if (attrValue == 1) { + curServ->attribute |= flag; + } + } else { + curServ->attribute &= ~flag; + INIT_LOGE("%s critical param invalid", curServ->name); + return SERVICE_FAILURE; + } + } else { + INIT_LOGE("%s critical type error", curServ->name); + return SERVICE_FAILURE; + } + return SERVICE_SUCCESS; +} + int ParseOneService(const cJSON *curItem, Service *service) { INIT_CHECK_RETURN_VALUE(curItem != NULL && service != NULL, SERVICE_FAILURE); @@ -540,7 +597,7 @@ int ParseOneService(const cJSON *curItem, Service *service) INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get once flag for service %s", service->name); ret = GetServiceAttr(curItem, service, IMPORTANT_STR_IN_CFG, SERVICE_ATTR_IMPORTANT, SetImportantValue); INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get import flag for service %s", service->name); - ret = GetServiceAttr(curItem, service, CRITICAL_STR_IN_CFG, SERVICE_ATTR_CRITICAL, NULL); + ret = GetCritical(curItem, service, CRITICAL_STR_IN_CFG, SERVICE_ATTR_CRITICAL); INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get critical flag for service %s", service->name); ret = GetServiceAttr(curItem, service, DISABLED_STR_IN_CFG, SERVICE_ATTR_DISABLED, NULL); INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get disabled flag for service %s", service->name);