提交 f5ed759c 编写于 作者: O openharmony_ci 提交者: Gitee

!201 add: socket service start ondemand

Merge pull request !201 from 熊磊/init122401
...@@ -41,6 +41,7 @@ if (defined(ohos_lite)) { ...@@ -41,6 +41,7 @@ if (defined(ohos_lite)) {
"init/lite/init_reboot.c", "init/lite/init_reboot.c",
"init/lite/init_service.c", "init/lite/init_service.c",
"init/lite/init_signal_handler.c", "init/lite/init_signal_handler.c",
"init/lite/init_socket_manager.c",
] ]
sources += init_common_sources sources += init_common_sources
...@@ -106,6 +107,7 @@ if (defined(ohos_lite)) { ...@@ -106,6 +107,7 @@ if (defined(ohos_lite)) {
"init/standard/init_reboot.c", "init/standard/init_reboot.c",
"init/standard/init_service.c", "init/standard/init_service.c",
"init/standard/init_signal_handler.c", "init/standard/init_signal_handler.c",
"init/standard/init_socket_manager.c",
"init/standard/switch_root.c", "init/standard/switch_root.c",
] ]
......
...@@ -44,6 +44,7 @@ extern "C" { ...@@ -44,6 +44,7 @@ extern "C" {
#define SERVICE_ATTR_DISABLED 0x040 // disabled #define SERVICE_ATTR_DISABLED 0x040 // disabled
#define SERVICE_ATTR_CONSOLE 0x080 // console #define SERVICE_ATTR_CONSOLE 0x080 // console
#define SERVICE_ATTR_DYNAMIC 0x100 // dynamic service #define SERVICE_ATTR_DYNAMIC 0x100 // dynamic service
#define SERVICE_ATTR_ONDEMAND 0x200 // ondemand, manage socket by init
#define MAX_SERVICE_NAME 32 #define MAX_SERVICE_NAME 32
#define MAX_WRITEPID_FILES 100 #define MAX_WRITEPID_FILES 100
......
...@@ -50,11 +50,19 @@ Service *GetServiceByPid(pid_t pid); ...@@ -50,11 +50,19 @@ Service *GetServiceByPid(pid_t pid);
Service *GetServiceByName(const char *servName); Service *GetServiceByName(const char *servName);
cJSON *GetArrayItem(const cJSON *fileRoot, int *arrSize, const char *arrName); cJSON *GetArrayItem(const cJSON *fileRoot, int *arrSize, const char *arrName);
int ParseOneService(const cJSON *curItem, Service *service); int ParseOneService(const cJSON *curItem, Service *service);
void SocketPollInit(int sockFd, const char* serviceName);
int CreateAndPollSocket(Service *service);
void StartServiceByName(const char *serviceName, bool checkDynamic); void StartServiceByName(const char *serviceName, bool checkDynamic);
void StopServiceByName(const char *serviceName); void StopServiceByName(const char *serviceName);
void StopAllServices(int flags); void StopAllServices(int flags);
void ParseAllServices(const cJSON *fileRoot); void ParseAllServices(const cJSON *fileRoot);
void ReleaseService(Service *service); void ReleaseService(Service *service);
static inline bool IsOnDemandService(Service *service)
{
return !!(service->attribute & SERVICE_ATTR_ONDEMAND);
}
#ifdef OHOS_SERVICE_DUMP #ifdef OHOS_SERVICE_DUMP
void DumpAllServices(); void DumpAllServices();
#endif #endif
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "init_cmds.h" #include "init_cmds.h"
#include "init_log.h" #include "init_log.h"
#include "init_service.h" #include "init_service.h"
#include "init_service_manager.h"
#include "init_service_socket.h" #include "init_service_socket.h"
#include "init_utils.h" #include "init_utils.h"
#include "securec.h" #include "securec.h"
...@@ -204,8 +205,11 @@ int ServiceStart(Service *service) ...@@ -204,8 +205,11 @@ int ServiceStart(Service *service)
} }
int pid = fork(); int pid = fork();
if (pid == 0) { if (pid == 0) {
int ret = CreateServiceSocket(service->socketCfg); if (!IsOnDemandService(service)) {
INIT_ERROR_CHECK(ret >= 0, _exit(PROCESS_EXIT_CODE), "service %s exit! create socket failed!", service->name); int ret = CreateServiceSocket(service->socketCfg);
INIT_ERROR_CHECK(ret >= 0, _exit(PROCESS_EXIT_CODE),
"service %s exit! create socket failed!", service->name);
}
CreateServiceFile(service->fileCfg); CreateServiceFile(service->fileCfg);
if (service->attribute & SERVICE_ATTR_CONSOLE) { if (service->attribute & SERVICE_ATTR_CONSOLE) {
OpenConsole(); OpenConsole();
...@@ -279,6 +283,20 @@ static int ExecRestartCmd(const Service *service) ...@@ -279,6 +283,20 @@ static int ExecRestartCmd(const Service *service)
return SERVICE_SUCCESS; return SERVICE_SUCCESS;
} }
static void PollSocketAfresh(Service *service)
{
if (service->socketCfg == NULL) {
INIT_LOGE("service %s socket config is NULL!", service->name);
return;
}
ServiceSocket *tmpSock = service->socketCfg;
while (tmpSock != NULL) {
SocketPollInit(tmpSock->sockFd, service->name);
tmpSock = tmpSock->next;
}
return;
}
void ServiceReap(Service *service) void ServiceReap(Service *service)
{ {
INIT_CHECK(service != NULL, return); INIT_CHECK(service != NULL, return);
...@@ -291,7 +309,9 @@ void ServiceReap(Service *service) ...@@ -291,7 +309,9 @@ void ServiceReap(Service *service)
return; return;
} }
CloseServiceSocket(service->socketCfg); if (!IsOnDemandService(service)) {
CloseServiceSocket(service->socketCfg);
}
CloseServiceFile(service->fileCfg); CloseServiceFile(service->fileCfg);
// stopped by system-init itself, no need to restart even if it is not one-shot service // stopped by system-init itself, no need to restart even if it is not one-shot service
if (service->attribute & SERVICE_ATTR_NEED_STOP) { if (service->attribute & SERVICE_ATTR_NEED_STOP) {
...@@ -322,6 +342,11 @@ void ServiceReap(Service *service) ...@@ -322,6 +342,11 @@ void ServiceReap(Service *service)
return; return;
} }
} }
// service no need to restart which socket managed by init until socket message detected
if (IsOnDemandService(service)) {
PollSocketAfresh(service);
return;
}
int ret; int ret;
if (service->restartArg != NULL) { if (service->restartArg != NULL) {
......
...@@ -359,6 +359,9 @@ static int ParseServiceSocket(const cJSON *curArrItem, Service *curServ) ...@@ -359,6 +359,9 @@ static int ParseServiceSocket(const cJSON *curArrItem, Service *curServ)
break; break;
} }
} }
if (IsOnDemandService(curServ)) {
ret = CreateAndPollSocket(curServ);
}
return ret; return ret;
} }
...@@ -466,11 +469,28 @@ static int GetDynamicService(const cJSON *curArrItem, Service *curServ) ...@@ -466,11 +469,28 @@ static int GetDynamicService(const cJSON *curArrItem, Service *curServ)
return SERVICE_SUCCESS; return SERVICE_SUCCESS;
} }
static int GetServiceOnDemand(const cJSON *curArrItem, Service *curServ)
{
cJSON *item = cJSON_GetObjectItem(curArrItem, "ondemand");
if (item == NULL) {
return SERVICE_SUCCESS;
}
INIT_ERROR_CHECK(cJSON_IsBool(item), return SERVICE_FAILURE,
"Service : %s ondemand value only support bool.", curServ->name);
bool isOnDemand = (bool)cJSON_GetNumberValue(item);
INIT_INFO_CHECK(isOnDemand, return SERVICE_SUCCESS,
"Service : %s ondemand value is false, it will be manage socket by itself", curServ->name);
curServ->attribute |= SERVICE_ATTR_ONDEMAND;
return SERVICE_SUCCESS;
}
static int CheckServiceKeyName(const cJSON *curService) static int CheckServiceKeyName(const cJSON *curService)
{ {
char *cfgServiceKeyList[] = { char *cfgServiceKeyList[] = {
"name", "path", "uid", "gid", "once", "importance", "caps", "disabled", "name", "path", "uid", "gid", "once", "importance", "caps", "disabled",
"writepid", "critical", "socket", "console", "dynamic", "file", "writepid", "critical", "socket", "console", "dynamic", "file", "ondemand",
#ifdef WITH_SELINUX #ifdef WITH_SELINUX
SECON_STR_IN_CFG, SECON_STR_IN_CFG,
#endif // WITH_SELINUX #endif // WITH_SELINUX
...@@ -533,6 +553,8 @@ int ParseOneService(const cJSON *curItem, Service *service) ...@@ -533,6 +553,8 @@ int ParseOneService(const cJSON *curItem, Service *service)
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get caps for service %s", service->name); INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get caps for service %s", service->name);
ret = GetDynamicService(curItem, service); ret = GetDynamicService(curItem, service);
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get dynamic flag for service %s", service->name); INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get dynamic flag for service %s", service->name);
ret = GetServiceOnDemand(curItem, service);
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get ondemand flag for service %s", service->name);
return ret; return ret;
} }
......
/*
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "init_service_manager.h"
void SocketPollInit(int sockFd, const char* serviceName)
{
return;
}
int CreateAndPollSocket(Service *service)
{
return 0;
}
/*
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sys/epoll.h>
#include "init_log.h"
#include "init_param.h"
#include "init_service_manager.h"
#include "securec.h"
#include "uv.h"
#define POLL_HANDLER_COUNT 1024
uv_poll_t g_socketPollHandler[POLL_HANDLER_COUNT];
static int handlerCounter = 0;
static void UVSocketPollHandler(uv_poll_t* handle, int status, int events)
{
if (handle == NULL) {
INIT_LOGE("handle is NULL!");
return;
}
char paramName[PARAM_NAME_LEN_MAX] = { 0 };
char paramValue[PARAM_VALUE_LEN_MAX] = { 0 };
unsigned int len = PARAM_VALUE_LEN_MAX;
INIT_CHECK_ONLY_ELOG(snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.socket.%d",
handle->io_watcher.fd) >= 0, "snprintf_s paramName error %d ", errno);
int ret = SystemReadParam(paramName, paramValue, &len);
if (ret != 0) {
INIT_LOGE("Failed to read param, param name = %s", paramName);
}
INIT_LOGI("Socket information detected, sockFd:%d service name:%s", handle->io_watcher.fd, paramValue);
uv_poll_stop(handle);
StartServiceByName(paramValue, false);
return;
}
static void SetSocketParam(Service *service)
{
char paramName[PARAM_NAME_LEN_MAX] = { 0 };
ServiceSocket *tmpSock = service->socketCfg;
while (tmpSock != NULL) {
INIT_CHECK_ONLY_ELOG(snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.socket.%d",
tmpSock->sockFd) >= 0, "snprintf_s paramName error %d ", errno);
SystemWriteParam(paramName, service->name);
(void)memset_s(paramName, PARAM_NAME_LEN_MAX, 0, PARAM_NAME_LEN_MAX);
tmpSock = tmpSock->next;
}
}
void SocketPollInit(int sockFd, const char* serviceName)
{
if (handlerCounter >= POLL_HANDLER_COUNT) {
INIT_LOGE("Socket poll handler is not enough!");
return;
}
int ret = uv_poll_init_with_block_socket(uv_default_loop(), &g_socketPollHandler[handlerCounter], sockFd);
if (ret != 0) {
INIT_LOGE("Failed to init socket poll!");
return;
}
ret = uv_poll_start(&g_socketPollHandler[handlerCounter], UV_READABLE, UVSocketPollHandler);
if (ret != 0) {
INIT_LOGE("Failed to start socket poll!");
return;
}
handlerCounter += 1;
INIT_LOGI("Start to poll socket, sockFd:%d service name:%s", sockFd, serviceName);
}
int CreateAndPollSocket(Service *service)
{
int ret = CreateServiceSocket(service->socketCfg);
if (ret != 0) {
INIT_LOGE("Create socket failed!");
return SERVICE_FAILURE;
}
SetSocketParam(service);
ServiceSocket *tmpSock = service->socketCfg;
while (tmpSock != NULL) {
SocketPollInit(tmpSock->sockFd, service->name);
tmpSock = tmpSock->next;
}
return 0;
}
...@@ -57,6 +57,7 @@ ohos_unittest("init_ut") { ...@@ -57,6 +57,7 @@ ohos_unittest("init_ut") {
"//base/startup/init_lite/services/init/standard/init_reboot.c", "//base/startup/init_lite/services/init/standard/init_reboot.c",
"//base/startup/init_lite/services/init/standard/init_service.c", "//base/startup/init_lite/services/init/standard/init_service.c",
"//base/startup/init_lite/services/init/standard/init_signal_handler.c", "//base/startup/init_lite/services/init/standard/init_signal_handler.c",
"//base/startup/init_lite/services/init/standard/init_socket_manager.c",
"//base/startup/init_lite/services/log/init_log.c", "//base/startup/init_lite/services/log/init_log.c",
"//base/startup/init_lite/services/param/adapter/param_dac.c", "//base/startup/init_lite/services/param/adapter/param_dac.c",
"//base/startup/init_lite/services/param/adapter/param_libuvadp.c", "//base/startup/init_lite/services/param/adapter/param_libuvadp.c",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册