mirror of
https://gitee.com/openharmony/startup_init
synced 2025-03-04 18:47:46 +00:00
!201 add: socket service start ondemand
Merge pull request !201 from 熊磊/init122401
This commit is contained in:
commit
f5ed759c4b
@ -41,6 +41,7 @@ if (defined(ohos_lite)) {
|
||||
"init/lite/init_reboot.c",
|
||||
"init/lite/init_service.c",
|
||||
"init/lite/init_signal_handler.c",
|
||||
"init/lite/init_socket_manager.c",
|
||||
]
|
||||
|
||||
sources += init_common_sources
|
||||
@ -106,6 +107,7 @@ if (defined(ohos_lite)) {
|
||||
"init/standard/init_reboot.c",
|
||||
"init/standard/init_service.c",
|
||||
"init/standard/init_signal_handler.c",
|
||||
"init/standard/init_socket_manager.c",
|
||||
"init/standard/switch_root.c",
|
||||
]
|
||||
|
||||
|
@ -44,6 +44,7 @@ extern "C" {
|
||||
#define SERVICE_ATTR_DISABLED 0x040 // disabled
|
||||
#define SERVICE_ATTR_CONSOLE 0x080 // console
|
||||
#define SERVICE_ATTR_DYNAMIC 0x100 // dynamic service
|
||||
#define SERVICE_ATTR_ONDEMAND 0x200 // ondemand, manage socket by init
|
||||
|
||||
#define MAX_SERVICE_NAME 32
|
||||
#define MAX_WRITEPID_FILES 100
|
||||
|
@ -50,11 +50,19 @@ Service *GetServiceByPid(pid_t pid);
|
||||
Service *GetServiceByName(const char *servName);
|
||||
cJSON *GetArrayItem(const cJSON *fileRoot, int *arrSize, const char *arrName);
|
||||
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 StopServiceByName(const char *serviceName);
|
||||
void StopAllServices(int flags);
|
||||
void ParseAllServices(const cJSON *fileRoot);
|
||||
void ReleaseService(Service *service);
|
||||
|
||||
static inline bool IsOnDemandService(Service *service)
|
||||
{
|
||||
return !!(service->attribute & SERVICE_ATTR_ONDEMAND);
|
||||
}
|
||||
|
||||
#ifdef OHOS_SERVICE_DUMP
|
||||
void DumpAllServices();
|
||||
#endif
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "init_cmds.h"
|
||||
#include "init_log.h"
|
||||
#include "init_service.h"
|
||||
#include "init_service_manager.h"
|
||||
#include "init_service_socket.h"
|
||||
#include "init_utils.h"
|
||||
#include "securec.h"
|
||||
@ -204,8 +205,11 @@ int ServiceStart(Service *service)
|
||||
}
|
||||
int pid = fork();
|
||||
if (pid == 0) {
|
||||
int ret = CreateServiceSocket(service->socketCfg);
|
||||
INIT_ERROR_CHECK(ret >= 0, _exit(PROCESS_EXIT_CODE), "service %s exit! create socket failed!", service->name);
|
||||
if (!IsOnDemandService(service)) {
|
||||
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);
|
||||
if (service->attribute & SERVICE_ATTR_CONSOLE) {
|
||||
OpenConsole();
|
||||
@ -279,6 +283,20 @@ static int ExecRestartCmd(const Service *service)
|
||||
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)
|
||||
{
|
||||
INIT_CHECK(service != NULL, return);
|
||||
@ -291,7 +309,9 @@ void ServiceReap(Service *service)
|
||||
return;
|
||||
}
|
||||
|
||||
CloseServiceSocket(service->socketCfg);
|
||||
if (!IsOnDemandService(service)) {
|
||||
CloseServiceSocket(service->socketCfg);
|
||||
}
|
||||
CloseServiceFile(service->fileCfg);
|
||||
// stopped by system-init itself, no need to restart even if it is not one-shot service
|
||||
if (service->attribute & SERVICE_ATTR_NEED_STOP) {
|
||||
@ -322,6 +342,11 @@ void ServiceReap(Service *service)
|
||||
return;
|
||||
}
|
||||
}
|
||||
// service no need to restart which socket managed by init until socket message detected
|
||||
if (IsOnDemandService(service)) {
|
||||
PollSocketAfresh(service);
|
||||
return;
|
||||
}
|
||||
|
||||
int ret;
|
||||
if (service->restartArg != NULL) {
|
||||
|
@ -359,6 +359,9 @@ static int ParseServiceSocket(const cJSON *curArrItem, Service *curServ)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (IsOnDemandService(curServ)) {
|
||||
ret = CreateAndPollSocket(curServ);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -466,11 +469,28 @@ static int GetDynamicService(const cJSON *curArrItem, Service *curServ)
|
||||
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)
|
||||
{
|
||||
char *cfgServiceKeyList[] = {
|
||||
"name", "path", "uid", "gid", "once", "importance", "caps", "disabled",
|
||||
"writepid", "critical", "socket", "console", "dynamic", "file",
|
||||
"writepid", "critical", "socket", "console", "dynamic", "file", "ondemand",
|
||||
#ifdef WITH_SELINUX
|
||||
SECON_STR_IN_CFG,
|
||||
#endif // WITH_SELINUX
|
||||
@ -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);
|
||||
ret = GetDynamicService(curItem, service);
|
||||
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;
|
||||
}
|
||||
|
||||
|
25
services/init/lite/init_socket_manager.c
Normal file
25
services/init/lite/init_socket_manager.c
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
94
services/init/standard/init_socket_manager.c
Normal file
94
services/init/standard/init_socket_manager.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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") {
|
||||
"//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_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/param/adapter/param_dac.c",
|
||||
"//base/startup/init_lite/services/param/adapter/param_libuvadp.c",
|
||||
|
Loading…
x
Reference in New Issue
Block a user