mirror of
https://gitee.com/openharmony/startup_init
synced 2024-12-24 11:55:27 +00:00
add: socket service start ondemand
Signed-off-by: xionglei6 <xionglei6@huawei.com>
This commit is contained in:
parent
b6ee22cccd
commit
4be5c06ffb
@ -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
|
||||
|
@ -46,10 +46,16 @@ typedef struct {
|
||||
int serviceCount;
|
||||
} ServiceSpace;
|
||||
|
||||
inline bool IsOnDemandService(Service *service)
|
||||
{
|
||||
return !!(service->attribute & SERVICE_ATTR_ONDEMAND);
|
||||
}
|
||||
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);
|
||||
|
@ -32,6 +32,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"
|
||||
@ -203,8 +204,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();
|
||||
@ -278,6 +282,20 @@ static int ExecRestartCmd(const Service *service)
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
static void PollSocketAfresh(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);
|
||||
@ -290,7 +308,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) {
|
||||
@ -321,6 +341,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) {
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "init.h"
|
||||
#include "init_jobs_internal.h"
|
||||
#include "init_log.h"
|
||||
#include "init_param.h"
|
||||
#include "init_service_file.h"
|
||||
#include "init_service_socket.h"
|
||||
#include "init_utils.h"
|
||||
@ -359,6 +360,9 @@ static int ParseServiceSocket(const cJSON *curArrItem, Service *curServ)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (IsOnDemandService(curServ)) {
|
||||
ret = CreateAndPollSocket(curServ);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -466,11 +470,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 +554,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_user_defined(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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user