This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit 84e87a5158134b867480a9ac01070e6917ff5311 Author: wangjianyu3 <[email protected]> AuthorDate: Fri Oct 10 21:48:38 2025 +0800 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]> --- system/nxinit/init.c | 9 +++++---- system/nxinit/service.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- system/nxinit/service.h | 8 +++++++- 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/system/nxinit/init.c b/system/nxinit/init.c index 52b71728f..a1482f693 100644 --- a/system/nxinit/init.c +++ b/system/nxinit/init.c @@ -75,6 +75,7 @@ static void reap_process(FAR struct service_manager_s *sm, FAR const char *status; FAR struct service_s *service; int wstatus; + int ret; int pid; for (; ; ) @@ -93,12 +94,12 @@ static void reap_process(FAR struct service_manager_s *sm, else if (WIFEXITED(wstatus)) { status = "status"; - wstatus = WEXITSTATUS(wstatus); + ret = WEXITSTATUS(wstatus); } else if (WIFSIGNALED(wtatus)) { status = "signal"; - wstatus = WTERMSIG(wstatus); + ret = WTERMSIG(wstatus); } else { @@ -115,12 +116,12 @@ static void reap_process(FAR struct service_manager_s *sm, if (service != NULL) { name = service->argv[1]; - init_service_reap(service); + init_service_reap(service, ret); } init_log(service ? LOG_WARNING : LOG_DEBUG, "%s '%s' pid %d exited %s %d", - service ? "Service" : "Command", name, pid, status, wstatus); + service ? "Service" : "Command", name, pid, status, ret); } } diff --git a/system/nxinit/service.c b/system/nxinit/service.c index 49f4d4c49..0d39bb614 100644 --- a/system/nxinit/service.c +++ b/system/nxinit/service.c @@ -25,6 +25,7 @@ ****************************************************************************/ #include <nuttx/clock.h> +#include <sys/boardctl.h> #include <assert.h> #include <errno.h> @@ -99,6 +100,10 @@ static int option_override(FAR struct service_manager_s *sm, int argc, FAR char **argv); static int option_oneshot(FAR struct service_manager_s *sm, int argc, FAR char **argv); +#ifdef CONFIG_BOARDCTL_RESET +static int option_reboot_on_failure(FAR struct service_manager_s *sm, + int argc, FAR char **argv); +#endif /**************************************************************************** * Private Data @@ -111,6 +116,9 @@ static const struct cmd_map_s g_option[] = {"restart_period", 2, 2, option_restart_period}, {"override", 1, 1, option_override}, {"oneshot", 1, 1, option_oneshot}, +#ifdef CONFIG_BOARDCTL_RESET + {"reboot_on_failure", 2, 2, option_reboot_on_failure}, +#endif }; #ifdef CONFIG_SYSTEM_NXINIT_DEBUG @@ -159,7 +167,7 @@ static int kill_service(FAR struct service_s *service, int signo) ret = -errno; if (ret == -ESRCH) { - init_service_reap(service); + init_service_reap(service, 0); } } @@ -261,6 +269,17 @@ static int option_oneshot(FAR struct service_manager_s *sm, return 0; } +#ifdef CONFIG_BOARDCTL_RESET +static int option_reboot_on_failure(FAR struct service_manager_s *sm, + int argc, FAR char **argv) +{ + FAR struct service_s *s = list_last_entry(&sm->services, struct service_s, + node); + s->reset_reason = atoi(argv[1]); + return 0; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -371,8 +390,25 @@ init_service_find_by_pid(FAR struct service_manager_s *sm, const int pid) return NULL; } -void init_service_reap(FAR struct service_s *service) +void init_service_reap(FAR struct service_s *service, int status) { +#ifdef CONFIG_BOARDCTL_RESET + int ret; + + if (status && service->reset_reason >= 0) + { + init_err("Reboot on failure of service '%s' reason %d", + service->argv[1], service->reset_reason); + ret = boardctl(BOARDIOC_RESET, service->reset_reason); + if (ret < 0) + { + init_err("Reset failed %d", errno); + } + } +#else + UNUSED(status); +#endif + remove_flags(service, SVC_RUNNING); if (check_flags(service, SVC_ONESHOT)) { @@ -404,6 +440,7 @@ int init_service_start(FAR struct service_s *service) if (ret != 0) { init_err("Starting service '%s': %d", service->argv[1], ret); + init_service_reap(service, ret); return -ret; } @@ -536,6 +573,9 @@ int init_service_parse(FAR const struct parser_s *parser, } s->restart_period = CONFIG_SYSTEM_NXINIT_SERVICE_RESTART_PERIOD; +#ifdef CONFIG_BOARDCTL_RESET + s->reset_reason = -1; +#endif list_initialize(&s->classes); list_add_tail(&sm->services, &s->node); } @@ -618,6 +658,9 @@ void init_dump_service(FAR struct service_s *s) } init_debug(" restart_period: %d", s->restart_period); +#ifdef CONFIG_BOARDCTL_RESET + init_debug(" reboot_on_failure: %d", s->reset_reason); +#endif if (s->flags) { diff --git a/system/nxinit/service.h b/system/nxinit/service.h index 303a44584..d76406e56 100644 --- a/system/nxinit/service.h +++ b/system/nxinit/service.h @@ -100,6 +100,12 @@ struct service_s struct timespec time_kill; int restart_period; pid_t pid; + + /* The "target" of service option "reboot_on_failure" */ + +#ifdef CONFIG_BOARDCTL_RESET + int reset_reason; +#endif }; struct service_manager_s @@ -112,7 +118,7 @@ struct service_manager_s ****************************************************************************/ int init_service_refresh(FAR struct service_manager_s *sm); -void init_service_reap(FAR struct service_s *service); +void init_service_reap(FAR struct service_s *service, int status); int init_service_start(FAR struct service_s *service); int init_service_stop(FAR struct service_s *service); int init_service_start_by_class(FAR struct service_manager_s *sm,
