You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2026/10/15 11:47:35 UTC
(nuttx-apps) 02/02: system/nxinit: add stdout and stderr service options
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit 22f51f210f5d4d41df064ae38acd4b8fe8dbb1e9
Author: wangjianyu3 <wa...@xiaomi.com>
AuthorDate: Wed Oct 14 14:32:13 2026 +0800
system/nxinit: add stdout and stderr service options
Redirect a service's stdout/stderr to a file (nsh "cmd > file" style)
behind SYSTEM_NXINIT_SERVICE_REDIR (default n, not recommended). Share
the console file actions and string assignment as common helpers.
Assisted-by: OpenCode:mimo-2.6-pro
Signed-off-by: wangjianyu3 <wa...@xiaomi.com>
---
system/nxinit/Kconfig | 11 +++
system/nxinit/service.c | 237 +++++++++++++++++++++++++++++++++++-------------
system/nxinit/service.h | 5 +
3 files changed, 191 insertions(+), 62 deletions(-)
diff --git a/system/nxinit/Kconfig b/system/nxinit/Kconfig
index 4b0d242bf..48a78263b 100644
--- a/system/nxinit/Kconfig
+++ b/system/nxinit/Kconfig
@@ -127,6 +127,17 @@ config SYSTEM_NXINIT_CONSOLE_DEV
comment "NXInit Testing"
+config SYSTEM_NXINIT_SERVICE_REDIR
+ bool "Service stdout/stderr redirection options (not recommended)"
+ default n
+ ---help---
+ Enable the "stdout <path>" and "stderr <path>" service options,
+ which redirect a service's stdout/stderr to a file like nsh
+ "cmd > file". They are not Android init service options and
+ are not recommended: a service should log through its log
+ interface instead. Only meant to keep rcS redirections when
+ moving a board from nsh to init.
+
config SYSTEM_NXINIT_TEST
bool "NxInit unit tests"
default n
diff --git a/system/nxinit/service.c b/system/nxinit/service.c
index bfdd99367..c4df0bbe2 100644
--- a/system/nxinit/service.c
+++ b/system/nxinit/service.c
@@ -106,6 +106,12 @@ static int option_oneshot(FAR struct service_manager_s *sm,
int argc, FAR char **argv);
static int option_console(FAR struct service_manager_s *sm,
int argc, FAR char **argv);
+#ifdef CONFIG_SYSTEM_NXINIT_SERVICE_REDIR
+static int option_stdout(FAR struct service_manager_s *sm,
+ int argc, FAR char **argv);
+static int option_stderr(FAR struct service_manager_s *sm,
+ int argc, FAR char **argv);
+#endif
#ifdef CONFIG_BOARDCTL_RESET
static int option_reboot_on_failure(FAR struct service_manager_s *sm,
int argc, FAR char **argv);
@@ -124,6 +130,10 @@ static const struct cmd_map_s g_option[] =
{"override", 1, 1, option_override},
{"oneshot", 1, 1, option_oneshot},
{"console", 1, 2, option_console},
+#ifdef CONFIG_SYSTEM_NXINIT_SERVICE_REDIR
+ {"stdout", 2, 2, option_stdout},
+ {"stderr", 2, 2, option_stderr},
+#endif
#ifdef CONFIG_BOARDCTL_RESET
{"reboot_on_failure", 2, 2, option_reboot_on_failure},
#endif
@@ -208,6 +218,10 @@ static void remove_service(FAR struct service_s *service)
}
free(service->console);
+#ifdef CONFIG_SYSTEM_NXINIT_SERVICE_REDIR
+ free(service->stdout_path);
+ free(service->stderr_path);
+#endif
list_delete(&service->node);
free(service);
}
@@ -294,6 +308,32 @@ static int option_oneshot(FAR struct service_manager_s *sm,
return 0;
}
+/****************************************************************************
+ * Name: service_strdup
+ *
+ * Description:
+ * Duplicate 'src' into *dst, replacing any previous value. Option
+ * strings point into the parser line buffer, which is reused for the
+ * next line, so they must be duplicated here. On allocation failure
+ * the previous value is kept.
+ *
+ ****************************************************************************/
+
+static int service_strdup(FAR char **dst, FAR const char *src)
+{
+ FAR char *dup = strdup(src);
+
+ if (dup == NULL)
+ {
+ init_err("Alloc '%s'", src);
+ return -ENOMEM;
+ }
+
+ free(*dst);
+ *dst = dup;
+ return 0;
+}
+
/****************************************************************************
* Name: option_console
*
@@ -315,22 +355,32 @@ static int option_console(FAR struct service_manager_s *sm,
if (argc > 1)
{
- /* 'argv' points into the parser line buffer, which is reused for the
- * next line, so the device name must be duplicated here.
- */
-
- free(s->console);
- s->console = strdup(argv[1]);
- if (s->console == NULL)
- {
- init_err("Alloc console device");
- return -ENOMEM;
- }
+ return service_strdup(&s->console, argv[1]);
}
return 0;
}
+#ifdef CONFIG_SYSTEM_NXINIT_SERVICE_REDIR
+static int option_stdout(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);
+
+ return service_strdup(&s->stdout_path, argv[1]);
+}
+
+static int option_stderr(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);
+
+ return service_strdup(&s->stderr_path, argv[1]);
+}
+#endif
+
#ifdef CONFIG_BOARDCTL_RESET
static int option_reboot_on_failure(FAR struct service_manager_s *sm,
int argc, FAR char **argv)
@@ -343,6 +393,102 @@ static int option_reboot_on_failure(FAR struct service_manager_s *sm,
}
#endif
+/****************************************************************************
+ * Name: service_file_actions
+ *
+ * Description:
+ * Build the spawn file actions which redirect the stdio of a service:
+ * its console device when flagged SVC_CONSOLE and, with
+ * CONFIG_SYSTEM_NXINIT_SERVICE_REDIR, its stdout/stderr files. The
+ * actions are performed in the context of the new task, so the stdio of
+ * NxInit itself is left untouched. On error the actions are destroyed
+ * and a negative errno is returned.
+ *
+ ****************************************************************************/
+
+static int service_file_actions(FAR posix_spawn_file_actions_t *actions,
+ FAR struct service_s *service)
+{
+ int ret;
+
+ ret = posix_spawn_file_actions_init(actions);
+ if (ret != 0)
+ {
+ init_err("posix_spawn_file_actions_init %d", ret);
+ return -ret;
+ }
+
+#ifdef CONFIG_SYSTEM_NXINIT_SERVICE_REDIR
+ /* Without the redirection options the caller has already checked
+ * SVC_CONSOLE, so only check it again when redirection can add
+ * file actions of its own.
+ */
+
+ if (check_flags(service, SVC_CONSOLE))
+#endif
+ {
+ FAR const char *dev = service->console ?
+ service->console :
+ CONFIG_SYSTEM_NXINIT_CONSOLE_DEV;
+
+ ret = posix_spawn_file_actions_addopen(actions, STDIN_FILENO, dev,
+ O_RDWR, 0);
+ if (ret == 0)
+ {
+ ret = posix_spawn_file_actions_adddup2(actions, STDIN_FILENO,
+ STDOUT_FILENO);
+ }
+
+ if (ret == 0)
+ {
+ ret = posix_spawn_file_actions_adddup2(actions, STDIN_FILENO,
+ STDERR_FILENO);
+ }
+
+ if (ret != 0)
+ {
+ init_err("Add console '%s' file action %d", dev, ret);
+ goto errout;
+ }
+ }
+
+#ifdef CONFIG_SYSTEM_NXINIT_SERVICE_REDIR
+ if (service->stdout_path != NULL)
+ {
+ ret = posix_spawn_file_actions_addopen(actions, STDOUT_FILENO,
+ service->stdout_path,
+ O_WRONLY | O_CREAT | O_TRUNC,
+ 0666);
+ if (ret != 0)
+ {
+ init_err("Add stdout '%s' file action %d", service->stdout_path,
+ ret);
+ goto errout;
+ }
+ }
+
+ if (service->stderr_path != NULL)
+ {
+ ret = posix_spawn_file_actions_addopen(actions, STDERR_FILENO,
+ service->stderr_path,
+ O_WRONLY | O_CREAT | O_TRUNC,
+ 0666);
+ if (ret != 0)
+ {
+ init_err("Add stderr '%s' file action %d", service->stderr_path,
+ ret);
+ goto errout;
+ }
+ }
+#endif
+
+ return 0;
+
+errout:
+ posix_spawn_file_actions_destroy(actions);
+ return -ret;
+}
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -488,55 +634,6 @@ void init_service_reap(FAR struct service_s *service, int status)
}
}
-/****************************************************************************
- * Name: console_file_actions
- *
- * Description:
- * Build the spawn file actions which redirect the stdio of a service
- * flagged SVC_CONSOLE to its console device. The actions are performed
- * in the context of the new task, so the stdio of NxInit itself is left
- * untouched.
- *
- ****************************************************************************/
-
-static int console_file_actions(FAR posix_spawn_file_actions_t *actions,
- FAR struct service_s *service)
-{
- FAR const char *dev = service->console ?
- service->console : CONFIG_SYSTEM_NXINIT_CONSOLE_DEV;
- int ret;
-
- ret = posix_spawn_file_actions_init(actions);
- if (ret != 0)
- {
- init_err("posix_spawn_file_actions_init %d", ret);
- return -ret;
- }
-
- ret = posix_spawn_file_actions_addopen(actions, STDIN_FILENO, dev,
- O_RDWR, 0);
- if (ret == 0)
- {
- ret = posix_spawn_file_actions_adddup2(actions, STDIN_FILENO,
- STDOUT_FILENO);
- }
-
- if (ret == 0)
- {
- ret = posix_spawn_file_actions_adddup2(actions, STDIN_FILENO,
- STDERR_FILENO);
- }
-
- if (ret != 0)
- {
- init_err("Add console '%s' file action %d", dev, ret);
- posix_spawn_file_actions_destroy(actions);
- return -ret;
- }
-
- return 0;
-}
-
int init_service_start(FAR struct service_s *service)
{
FAR posix_spawn_file_actions_t *pactions = NULL;
@@ -581,9 +678,13 @@ int init_service_start(FAR struct service_s *service)
clock_gettime(CLOCK_MONOTONIC, &service->time_started);
- if (check_flags(service, SVC_CONSOLE))
+ if (check_flags(service, SVC_CONSOLE)
+#ifdef CONFIG_SYSTEM_NXINIT_SERVICE_REDIR
+ || service->stdout_path != NULL || service->stderr_path != NULL
+#endif
+ )
{
- ret = console_file_actions(&actions, service);
+ ret = service_file_actions(&actions, service);
if (ret < 0)
{
posix_spawnattr_destroy(&attr);
@@ -836,6 +937,18 @@ void init_dump_service(FAR struct service_s *s)
}
init_debug(" restart_period: %d", s->restart_period);
+#ifdef CONFIG_SYSTEM_NXINIT_SERVICE_REDIR
+ if (s->stdout_path != NULL)
+ {
+ init_debug(" stdout: '%s'", s->stdout_path);
+ }
+
+ if (s->stderr_path != NULL)
+ {
+ init_debug(" stderr: '%s'", s->stderr_path);
+ }
+
+#endif
#ifdef CONFIG_BOARDCTL_RESET
init_debug(" reboot_on_failure: %d", s->reset_reason);
#endif
diff --git a/system/nxinit/service.h b/system/nxinit/service.h
index be11c4299..1b93ab98f 100644
--- a/system/nxinit/service.h
+++ b/system/nxinit/service.h
@@ -116,6 +116,11 @@ struct service_s
FAR char *console;
+#ifdef CONFIG_SYSTEM_NXINIT_SERVICE_REDIR
+ FAR char *stdout_path;
+ FAR char *stderr_path;
+#endif
+
/* The "target" of service option "reboot_on_failure" */
#ifdef CONFIG_BOARDCTL_RESET