From 51c542b75ef67d59151f14757bc54a7e17543b5b Mon Sep 17 00:00:00 2001 From: wangjianyu3 Date: Thu, 25 Dec 2025 15:22:48 +0800 Subject: [PATCH] system/nxinit: Fix signal mask inheritance The init process has blocked all signals, spawned services would inherit that mask. This could cause services to miss important signals like SIGTERM during graceful shutdown. Signed-off-by: wangjianyu3 --- system/nxinit/builtin.c | 84 +++++++++++++++++++++++++++++------------ system/nxinit/service.c | 29 +++++++++++++- 2 files changed, 87 insertions(+), 26 deletions(-) diff --git a/system/nxinit/builtin.c b/system/nxinit/builtin.c index d300457f7..ba7a41bcf 100644 --- a/system/nxinit/builtin.c +++ b/system/nxinit/builtin.c @@ -183,6 +183,10 @@ static int cmd_exec(FAR struct action_manager_s *am, int init_builtin_run(FAR struct action_manager_s *am, int argc, FAR char **argv) { + char cmd[CONFIG_SYSTEM_NXINIT_RC_LINE_MAX]; + posix_spawnattr_t attr; + FAR char *args[4]; + sigset_t mask; pid_t pid; size_t i; int ret; @@ -203,35 +207,65 @@ int init_builtin_run(FAR struct action_manager_s *am, } } - ret = posix_spawnp(&pid, argv[0], NULL, NULL, argv, NULL); + ret = posix_spawnattr_init(&attr); if (ret != 0) { -#ifdef CONFIG_SYSTEM_SYSTEM - char cmd[CONFIG_SYSTEM_NXINIT_RC_LINE_MAX]; - - for (i = 0, cmd[i] = '\0'; i < argc; i++) - { - strlcat(cmd, argv[i], sizeof(cmd)); - if (i < argc - 1) - { - strcat(cmd, " "); - } - } - - init_debug("Executing nsh command '%s'", cmd); - ret = system(cmd); - if (WIFEXITED(ret)) - { - init_debug("NSH command '%s' exited %d", cmd, WEXITSTATUS(ret)); - return -WEXITSTATUS(ret); - } -#endif - - init_err("Executing command '%s': %d", argv[0], ret); - init_dump_args(argc, argv); + init_err("posix_spawnattr_init %d", ret); return -ret; } - init_debug("Executed command '%s' pid %d", argv[0], pid); + ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGMASK); + if (ret != 0) + { + init_err("posix_spawnattr_setflags %d", ret); + posix_spawnattr_destroy(&attr); + return -ret; + } + + sigemptyset(&mask); + ret = posix_spawnattr_setsigmask(&attr, &mask); + if (ret != 0) + { + init_err("posix_spawnattr_setsigmask %d", ret); + posix_spawnattr_destroy(&attr); + return -ret; + } + + for (i = 0, cmd[i] = '\0'; i < argc; i++) + { + strlcat(cmd, argv[i], sizeof(cmd)); + if (i < argc - 1) + { + strcat(cmd, " "); + } + } + + for (; ; ) + { + ret = posix_spawnp(&pid, argv[0], NULL, &attr, argv, NULL); + if (ret == 0) + { + init_debug("executed command '%s' pid %d", cmd, pid); + break; + } + + if (!strcmp("sh", argv[0])) + { + init_err("executing command '%s': %d", cmd, ret); + init_dump_args(argc, argv); + pid = -ret; + break; + } + + init_debug("command '%s': %d", argv[0], ret); + args[0] = "sh"; + args[1] = "-c"; + args[2] = cmd; + args[3] = NULL; + argc = nitems(args) - 1; + argv = args; + } + + posix_spawnattr_destroy(&attr); return pid; } diff --git a/system/nxinit/service.c b/system/nxinit/service.c index 7f582e6e4..7e840e7e7 100644 --- a/system/nxinit/service.c +++ b/system/nxinit/service.c @@ -427,6 +427,8 @@ void init_service_reap(FAR struct service_s *service, int status) int init_service_start(FAR struct service_s *service) { + posix_spawnattr_t attr; + sigset_t mask; int ret; int pid; @@ -439,8 +441,33 @@ int init_service_start(FAR struct service_s *service) return service->pid; } - ret = posix_spawnp(&pid, service->argv[2], NULL, NULL, &service->argv[2], + ret = posix_spawnattr_init(&attr); + if (ret != 0) + { + init_err("posix_spawnattr_init %d", ret); + return -ret; + } + + ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGMASK); + if (ret != 0) + { + init_err("posix_spawnattr_setflags %d", ret); + posix_spawnattr_destroy(&attr); + return -ret; + } + + sigemptyset(&mask); + ret = posix_spawnattr_setsigmask(&attr, &mask); + if (ret != 0) + { + init_err("posix_spawnattr_setsigmask %d", ret); + posix_spawnattr_destroy(&attr); + return -ret; + } + + ret = posix_spawnp(&pid, service->argv[2], NULL, &attr, &service->argv[2], environ); + posix_spawnattr_destroy(&attr); if (ret != 0) { init_err("Starting service '%s': %d", service->argv[1], ret);