Skip to content

Commit 0310a91

Browse files
system/nxinit: Add reboot_on_failure for service
Add support for the reboot_on_failure option to the service. When the execution of a command within a certain action fails (returning a non-zero status code), NxInit will continue to execute subsequent commands or actions and will not proactively terminate the startup process. To implement the functionality of "terminating the startup process after a command execution fails", there are two methods: a. Execute conditional statements (if/then/else/fi) via exec command, but this depends on sh: ``` on init exec -- set +e; \ mount -t fatfs /dev/data /data ; \ if [ $? -ne 0 ] ; \ then \ echo "failed" ; \ reboot ; \ else \ echo "succeed" ; \ fi; ``` b. Via service's oneshot + reboot_on_failure: /* Although the example uses sh, it does not depend on it and can be * replaced with any other Builtin Apps. */ ``` on init exec_start mkdir_tmp ls /tmp service mkdir_tmp sh -c "mkdir /tmp" reboot_on_failure 0 oneshot ``` Test - RC service console sh class core override > reboot_on_failure 0 restart_period 10000 - Runtime [ 0.150000] [ 3] [ 0] init_main: == Dump Services == ... [ 0.170000] [ 3] [ 0] init_main: Service 0x40486ea0 name 'console' path 'sh' [ 0.170000] [ 3] [ 0] init_main: pid: 0 [ 0.170000] [ 3] [ 0] init_main: arguments: [ 0.170000] [ 3] [ 0] init_main: [0] 'service' [ 0.170000] [ 3] [ 0] init_main: [1] 'console' [ 0.170000] [ 3] [ 0] init_main: [2] 'sh' [ 0.170000] [ 3] [ 0] init_main: classes: [ 0.170000] [ 3] [ 0] init_main: 'core' [ 0.170000] [ 3] [ 0] init_main: restart_period: 10000 > [ 0.170000] [ 3] [ 0] init_main: reboot_on_failure: 0 [ 0.170000] [ 3] [ 0] init_main: flags: [ 0.170000] [ 3] [ 0] init_main: 'override' ... [ 0.380000] [ 3] [ 0] init_main: started service 'console' pid 4 ... nsh> kill -9 4 [ 8.060000] [ 3] [ 0] init_main: service 'console' flag 0x20000004 add 0x4 [ 8.060000] [ 3] [ 0] init_main: -flag 'running' [ 8.060000] [ 3] [ 0] init_main: service 'console' flag 0x20000000 add 0x8 [ 8.060000] [ 3] [ 0] init_main: +flag 'restarting' > [ 8.060000] [ 3] [ 0] init_main: Error reboot on failure of service 'console' reason 0 Signed-off-by: wangjianyu3 <[email protected]>
1 parent 5a66436 commit 0310a91

File tree

3 files changed

+57
-7
lines changed

3 files changed

+57
-7
lines changed

system/nxinit/init.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ static void reap_process(FAR struct service_manager_s *sm,
7575
FAR const char *status;
7676
FAR struct service_s *service;
7777
int wstatus;
78+
int ret;
7879
int pid;
7980

8081
for (; ; )
@@ -93,12 +94,12 @@ static void reap_process(FAR struct service_manager_s *sm,
9394
else if (WIFEXITED(wstatus))
9495
{
9596
status = "status";
96-
wstatus = WEXITSTATUS(wstatus);
97+
ret = WEXITSTATUS(wstatus);
9798
}
9899
else if (WIFSIGNALED(wtatus))
99100
{
100101
status = "signal";
101-
wstatus = WTERMSIG(wstatus);
102+
ret = WTERMSIG(wstatus);
102103
}
103104
else
104105
{
@@ -115,12 +116,12 @@ static void reap_process(FAR struct service_manager_s *sm,
115116
if (service)
116117
{
117118
name = service->argv[1];
118-
init_service_reap(service);
119+
init_service_reap(service, ret);
119120
}
120121

121122
init_log(service ? LOG_WARNING : LOG_DEBUG,
122123
"%s '%s' pid %d exited %s %d",
123-
service ? "Service" : "Command", name, pid, status, wstatus);
124+
service ? "Service" : "Command", name, pid, status, ret);
124125
}
125126
}
126127

system/nxinit/service.c

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
****************************************************************************/
2626

2727
#include <nuttx/clock.h>
28+
#include <sys/boardctl.h>
2829

2930
#include <assert.h>
3031
#include <errno.h>
@@ -99,6 +100,10 @@ static int option_override(FAR struct service_manager_s *sm,
99100
int argc, FAR char **argv);
100101
static int option_oneshot(FAR struct service_manager_s *sm,
101102
int argc, FAR char **argv);
103+
#ifdef CONFIG_BOARDCTL_RESET
104+
static int option_reboot_on_failure(FAR struct service_manager_s *sm,
105+
int argc, FAR char **argv);
106+
#endif
102107

103108
/****************************************************************************
104109
* Private Data
@@ -111,6 +116,9 @@ static const struct cmd_map_s g_option[] =
111116
{"restart_period", 2, 2, option_restart_period},
112117
{"override", 1, 1, option_override},
113118
{"oneshot", 1, 1, option_oneshot},
119+
#ifdef CONFIG_BOARDCTL_RESET
120+
{"reboot_on_failure", 2, 2, option_reboot_on_failure},
121+
#endif
114122
};
115123

116124
#ifdef CONFIG_SYSTEM_NXINIT_DEBUG
@@ -159,7 +167,7 @@ static int kill_service(FAR struct service_s *service, int signo)
159167
ret = -errno;
160168
if (ret == -ESRCH)
161169
{
162-
init_service_reap(service);
170+
init_service_reap(service, 0);
163171
}
164172
}
165173

@@ -261,6 +269,17 @@ static int option_oneshot(FAR struct service_manager_s *sm,
261269
return 0;
262270
}
263271

272+
#ifdef CONFIG_BOARDCTL_RESET
273+
static int option_reboot_on_failure(FAR struct service_manager_s *sm,
274+
int argc, FAR char **argv)
275+
{
276+
FAR struct service_s *s = list_last_entry(&sm->services, struct service_s,
277+
node);
278+
s->reset_reason = atoi(argv[1]);
279+
return 0;
280+
}
281+
#endif
282+
264283
/****************************************************************************
265284
* Public Functions
266285
****************************************************************************/
@@ -371,8 +390,25 @@ init_service_find_by_pid(FAR struct service_manager_s *sm, const int pid)
371390
return NULL;
372391
}
373392

374-
void init_service_reap(FAR struct service_s *service)
393+
void init_service_reap(FAR struct service_s *service, int status)
375394
{
395+
#ifdef CONFIG_BOARDCTL_RESET
396+
int ret;
397+
398+
if (status && service->reset_reason >= 0)
399+
{
400+
init_err("Reboot on failure of service '%s' reason %d",
401+
service->argv[1], service->reset_reason);
402+
ret = boardctl(BOARDIOC_RESET, service->reset_reason);
403+
if (ret < 0)
404+
{
405+
init_err("Reset failed %d", errno);
406+
}
407+
}
408+
#else
409+
UNUSED(status);
410+
#endif
411+
376412
remove_flags(service, SVC_RUNNING);
377413
if (check_flags(service, SVC_ONESHOT))
378414
{
@@ -404,6 +440,7 @@ int init_service_start(FAR struct service_s *service)
404440
if (ret != 0)
405441
{
406442
init_err("Starting service '%s': %d", service->argv[1], ret);
443+
init_service_reap(service, ret);
407444
return -ret;
408445
}
409446

@@ -536,6 +573,9 @@ int init_service_parse(FAR const struct parser_s *parser,
536573
}
537574

538575
s->restart_period = CONFIG_SYSTEM_NXINIT_SERVICE_RESTART_PERIOD;
576+
#ifdef CONFIG_BOARDCTL_RESET
577+
s->reset_reason = -1;
578+
#endif
539579
list_initialize(&s->classes);
540580
list_add_tail(&sm->services, &s->node);
541581
}
@@ -618,6 +658,9 @@ void init_dump_service(FAR struct service_s *s)
618658
}
619659

620660
init_debug(" restart_period: %d", s->restart_period);
661+
#ifdef CONFIG_BOARDCTL_RESET
662+
init_debug(" reboot_on_failure: %d", s->reset_reason);
663+
#endif
621664

622665
if (s->flags)
623666
{

system/nxinit/service.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ struct service_s
100100
struct timespec time_kill;
101101
int restart_period;
102102
pid_t pid;
103+
104+
/* The "target" of service option "reboot_on_failure" */
105+
106+
#ifdef CONFIG_BOARDCTL_RESET
107+
int reset_reason;
108+
#endif
103109
};
104110

105111
struct service_manager_s
@@ -112,7 +118,7 @@ struct service_manager_s
112118
****************************************************************************/
113119

114120
int init_service_refresh(FAR struct service_manager_s *sm);
115-
void init_service_reap(FAR struct service_s *service);
121+
void init_service_reap(FAR struct service_s *service, int status);
116122
int init_service_start(FAR struct service_s *service);
117123
int init_service_stop(FAR struct service_s *service);
118124
int init_service_start_by_class(FAR struct service_manager_s *sm,

0 commit comments

Comments
 (0)