未验证 提交 859a3cbf 编写于 作者: O openharmony_ci 提交者: Gitee

!289 add: init添加 定时启动的能力

Merge pull request !289 from 熊磊/init129_3
......@@ -34,7 +34,8 @@ int ServiceControlWithExtra(const char *serviceName, int action, const char *ext
int ServiceControl(const char *serviceName, int action);
// Service status can set "running", "stopping", "stopped", "reseting". waitTimeout(s).
int ServiceWaitForStatus(const char *serviceName, const char *status, int waitTimeout);
int StartServiceByTimer(const char *serviceName, uint64_t timeout);
int StopServiceTimer(const char *serviceName);
#ifdef __cplusplus
#if __cplusplus
}
......
......@@ -198,3 +198,49 @@ int ServiceWaitForStatus(const char *serviceName, const char *status, int waitTi
BEGET_LOGI("Success wait");
return 0;
}
int StartServiceByTimer(const char *serviceName, uint64_t timeout)
{
if (serviceName == NULL) {
BEGET_LOGE("Request start serivce by timer with invalid service name");
return -1;
}
if (timeout == 0) {
// start service immediately.
return ServiceControl(serviceName, START);
}
// restrict timeout value, not too long.
char value[PARAM_VALUE_LEN_MAX] = {};
if (snprintf_s(value, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "%s|%lld", serviceName, timeout) == -1) {
BEGET_LOGE("Failed to build parameter value");
return -1;
}
if (SystemSetParameter("ohos.servicectrl.timer_start", value) != 0) {
BEGET_LOGE("Failed to set parameter \' ohos.servicectrl.timer_start \' with value \' %s \'", value);
return -1;
}
return 0;
}
int StopServiceTimer(const char *serviceName)
{
if (serviceName == NULL) {
BEGET_LOGE("Request stop serivce timer with invalid service name");
return -1;
}
char value[PARAM_VALUE_LEN_MAX] = {};
int ret = strncpy_s(value, PARAM_VALUE_LEN_MAX - 1, serviceName, strlen(serviceName));
if (ret < 0) {
BEGET_LOGE("Failed to copy service name to parameter");
return -1;
}
if (SystemSetParameter("ohos.servicectrl", value) != 0) {
BEGET_LOGE("Failed to set parameter \' ohos.servicectrl.timer_stop \' with value \' %s \'", value);
return -1;
}
return 0;
}
......@@ -46,6 +46,19 @@ static int main_cmd(BShellHandle shell, int argc, char **argv)
ServiceControlWithExtra(argv[1], 0, (const char **)argv + SERVICE_START_NUMBER, argc - SERVICE_START_NUMBER);
} else if (strcmp(argv[0], "stop") == 0) {
ServiceControlWithExtra(argv[1], 1, (const char **)argv + SERVICE_START_NUMBER, argc - SERVICE_START_NUMBER);
} else if (strcmp(argv[0], "timer_start") == 0) {
if (argc < SERVICE_START_NUMBER) {
return -1;
}
char *timeBuffer = argv[SERVICE_START_NUMBER];
errno = 0;
uint64_t timeout = strtoull(timeBuffer, NULL, 10);
if (errno != 0) {
return -1;
}
StartServiceByTimer(argv[1], timeout);
} else if (strcmp(argv[0], "timer_stop") == 0) {
StopServiceTimer(argv[1]);
} else {
ServiceControlUsage(shell, argc, argv);
}
......@@ -58,7 +71,9 @@ MODULE_CONSTRUCTOR(void)
{"service_control", main_cmd, "stop service", "service_control stop servicename", "service_control stop"},
{"service_control", main_cmd, "start service", "service_control start servicename", "service_control start"},
{"stop_service", main_cmd, "stop service", "stop_service servicename", ""},
{"start_service", main_cmd, "start service", "start_service servicename", ""}
{"start_service", main_cmd, "start service", "start_service servicename", ""},
{"timer_start", main_cmd, "start service by timer", "timer_start servicename timeout", ""},
{"timer_stop", main_cmd, "stop service timer", "timer_stop servicename", ""},
};
for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) {
BShellEnvRegitsterCmd(GetShellHandle(), &infos[i]);
......
......@@ -26,6 +26,7 @@
# include "init_selinux_param.h"
#endif // WITH_SELINUX
#include "list.h"
#include "loop_event.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
......@@ -47,6 +48,7 @@ extern "C" {
#define SERVICE_ATTR_CONSOLE 0x080 // console
#define SERVICE_ATTR_DYNAMIC 0x100 // dynamic service
#define SERVICE_ATTR_ONDEMAND 0x200 // ondemand, manage socket by init
#define SERVICE_ATTR_TIMERSTART 0x400 // Mark a service will be started by timer
#define MAX_SERVICE_NAME 32
#define MAX_APL_NAME 32
......@@ -65,6 +67,15 @@ extern "C" {
#define IsOnDemandService(service) \
(((service)->attribute & SERVICE_ATTR_ONDEMAND) == SERVICE_ATTR_ONDEMAND)
#define IsServiceWithTimerEnabled(service) \
(((service)->attribute & SERVICE_ATTR_TIMERSTART) == SERVICE_ATTR_TIMERSTART)
#define DisableServiceTimer(service) \
((service)->attribute &= ~SERVICE_ATTR_TIMERSTART)
#define EnableServiceTimer(service) \
((service)->attribute |= SERVICE_ATTR_TIMERSTART)
typedef enum {
START_MODE_CONDITION,
START_MODE_BOOT,
......@@ -134,6 +145,7 @@ typedef struct Service_ {
ServiceFile *fileCfg;
int *fds;
size_t fdCount;
TimerHandle timer;
ServiceJobs serviceJobs;
CpuArgs cpuInfo;
} Service;
......@@ -152,6 +164,8 @@ void CloseServiceFds(Service *service, bool needFree);
int UpdaterServiceFds(Service *service, int *fds, size_t fdCount);
int SetAccessToken(const Service *service);
void GetAccessToken(void);
void ServiceStopTimer(Service *service);
void ServiceStartTimer(Service *service, uint64_t timeout);
#ifdef __cplusplus
#if __cplusplus
......
......@@ -40,6 +40,7 @@
#include "init_service_socket.h"
#include "init_utils.h"
#include "fd_holder_internal.h"
#include "loop_event.h"
#include "securec.h"
#ifdef WITH_SELINUX
......@@ -299,7 +300,7 @@ int ServiceStart(Service *service)
DoJobNow(service->serviceJobs.jobsName[JOB_ON_START]);
}
(void)ClearEnvironment();
ClearEnvironment();
if (!IsOnDemandService(service)) {
int ret = CreateServiceSocket(service);
......@@ -351,6 +352,10 @@ int ServiceStop(Service *service)
if (service->fdCount != 0) {
CloseServiceFds(service, true);
}
if (IsServiceWithTimerEnabled(service)) {
ServiceStopTimer(service);
}
INIT_ERROR_CHECK(kill(service->pid, SIGKILL) == 0, return SERVICE_FAILURE,
"stop service %s pid %d failed! err %d.", service->name, service->pid, errno);
NotifyServiceChange(service->name, "stopping");
......@@ -424,6 +429,11 @@ void ServiceReap(Service *service)
return;
}
// If the service set timer
// which means the timer handler will start the service
// Init should not start it automatically.
INIT_CHECK(IsServiceWithTimerEnabled(service) == 0, return);
if (!IsOnDemandService(service)) {
CloseServiceSocket(service);
}
......@@ -469,9 +479,7 @@ void ServiceReap(Service *service)
INIT_CHECK_ONLY_ELOG(ret == SERVICE_SUCCESS, "Failed to exec restartArg for %s", service->name);
}
ret = ServiceStart(service);
if (ret != SERVICE_SUCCESS) {
INIT_LOGE("reap service %s start failed!", service->name);
}
INIT_CHECK_ONLY_ELOG(ret == SERVICE_SUCCESS, "reap service %s start failed!", service->name);
service->attribute &= (~SERVICE_ATTR_NEED_RESTART);
}
......@@ -535,3 +543,63 @@ int UpdaterServiceFds(Service *service, int *fds, size_t fdCount)
INIT_LOGI("Hold fd for service \' %s \' done", service->name);
return ret;
}
void ServiceStopTimer(Service *service)
{
INIT_ERROR_CHECK(service != NULL, return, "Stop timer with invalid service");
if (IsServiceWithTimerEnabled(service)) {
// Stop timer first
if (service->timer) {
LE_StopTimer(LE_GetDefaultLoop(), service->timer);
}
service->timer = NULL;
DisableServiceTimer(service);
}
}
static void ServiceTimerStartProcess(const TimerHandle handler, void *context)
{
UNUSED(handler);
Service *service = (Service *)context;
if (service == NULL) {
INIT_LOGE("Service timer process with invalid service");
return;
}
// OK, service is ready to start.
// Before start the service, stop service timer.
// make sure it will not enter timer handler next time.
ServiceStopTimer(service);
int ret = ServiceStart(service);
if (ret != SERVICE_SUCCESS) {
INIT_LOGE("Start service \' %s \' in timer failed");
}
}
void ServiceStartTimer(Service *service, uint64_t timeout)
{
bool oldTimerClean = false;
INIT_ERROR_CHECK(service != NULL, return, "Start timer with invalid service");
// If the service already set a timer.
// And a new request coming. close it and create a new one.
if (IsServiceWithTimerEnabled(service)) {
ServiceStopTimer(service);
oldTimerClean = true;
}
LE_STATUS status = LE_CreateTimer(LE_GetDefaultLoop(), &service->timer, ServiceTimerStartProcess,
(void *)service);
if (status != LE_SUCCESS) {
INIT_LOGE("Create service timer for service \' %s \' failed, status = %d", service->name, status);
if (oldTimerClean) {
INIT_LOGE("previous timer is cleared");
}
return;
}
status = LE_StartTimer(LE_GetDefaultLoop(), service->timer, timeout, 1);
if (status != LE_SUCCESS) {
INIT_LOGE("Start service timer for service \' %s \' failed, status = %d", service->name, status);
return;
}
EnableServiceTimer(service);
}
......@@ -282,6 +282,55 @@ static void DoLoadAccessTokenId(const struct CmdArgs *ctx)
LoadAccessTokenId();
}
static void DoTimerStart(const struct CmdArgs*ctx)
{
INIT_LOGI("Timer start service with arg = %s", ctx->argv[0]);
char *arg = ctx->argv[0];
int count = 0;
int expectedCount = 2;
char **splitArgs = SplitStringExt(ctx->argv[0], "|", &count, expectedCount);
if (splitArgs == NULL) {
INIT_LOGE("Call timer_start with invalid arguments");
return;
}
if (count != expectedCount) {
INIT_LOGE("Call timer_start with unexpect arguments %s", arg);
FreeStringVector(splitArgs, count);
return;
}
Service *service = GetServiceByName(splitArgs[0]);
if (service == NULL) {
INIT_LOGE("Cannot find service in timer_start command");
FreeStringVector(splitArgs, count);
return;
}
errno = 0;
uint64_t timeout = strtoull(splitArgs[1], NULL, DECIMAL_BASE);
if (errno != 0) {
INIT_LOGE("call timer_start with invalid timer");
FreeStringVector(splitArgs, count);
return;
}
// not need this anymore , release memory.
FreeStringVector(splitArgs, count);
ServiceStartTimer(service, timeout);
}
static void DoTimerStop(const struct CmdArgs*ctx)
{
INIT_LOGI("Stop service timer with arg = %s", ctx->argv[0]);
const char *serviceName = ctx->argv[0];
Service *service = GetServiceByName(serviceName);
if (service == NULL) {
INIT_LOGE("Cannot find service in timer_stop command");
return;
}
ServiceStopTimer(service);
}
static const struct CmdTable g_cmdTable[] = {
{ "exec ", 1, 10, DoExec },
{ "mknode ", 1, 5, DoMakeNode },
......@@ -297,6 +346,8 @@ static const struct CmdTable g_cmdTable[] = {
{ "mount_fstab ", 1, 1, DoMountFstabFile },
{ "umount_fstab ", 1, 1, DoUmountFstabFile },
{ "restorecon ", 0, 1, DoRestorecon },
{ "timer_start", 1, 1, DoTimerStart },
{ "timer_stop", 1, 1, DoTimerStop },
};
const struct CmdTable *GetCmdTable(int *number)
......
......@@ -182,7 +182,7 @@ static char *GetServiceCtrlName(ParamWorkSpace *workSpace, const char *name, con
"ohos.ctl.stop"
};
static char *installParam[] = {
"ohos.servicectrl"
"ohos.servicectrl."
};
static char *powerCtrlArg[][2] = {
{"reboot,shutdown", "reboot.shutdown"},
......@@ -206,7 +206,7 @@ static char *GetServiceCtrlName(ParamWorkSpace *workSpace, const char *name, con
}
for (size_t i = 0; i < ARRAY_LENGTH(installParam); i++) {
if (strcmp(name, installParam[i]) == 0) {
if (strncmp(name, installParam[i], strlen(installParam[i])) == 0) {
return BuildKey(workSpace, "%s.%s", name, value);
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册