system/nxinit: add fallback option to resolve preset service conflict

The preset kvdb service defined in parser.c conflicts with user-defined
kvdb service in board-level init.rc, causing:

  Error redefined service 'kvdb'

Add SVC_FALLBACK flag and fallback service option. When a service
is marked as fallback, it will be silently ignored if another
service with the same name already exists. This is the semantic
opposite of override:

- override: new definition replaces old
- fallback: new definition yields to old
- old has fallback + new arrives: old yields to new

If neither flag is set, duplicate service names still produce
EEXIST error as before.

Mark the preset kvdb service as fallback so that board-specific
init.rc can freely define its own kvdb service without conflict.

Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
This commit is contained in:
wangjianyu3 2026-08-28 21:14:06 +08:00 • committed by GUIDINGLI
parent 5f7db152b2
commit 2085e1ca96
2 changed files with 37 additions and 5 deletions

View file

@ -98,6 +98,8 @@ static int option_gentle_kill(FAR struct service_manager_s *sm,
int argc, FAR char **argv);
static int option_restart_period(FAR struct service_manager_s *sm,
int argc, FAR char **argv);
static int option_fallback(FAR struct service_manager_s *sm,
int argc, FAR char **argv);
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,
@ -118,6 +120,7 @@ static const struct cmd_map_s g_option[] =
{"class", 2, NXINIT_ACTION_CMD_ARGS_MAX, option_class},
{"gentle_kill", 1, 1, option_gentle_kill},
{"restart_period", 2, 2, option_restart_period},
{"fallback", 1, 1, option_fallback},
{"override", 1, 1, option_override},
{"oneshot", 1, 1, option_oneshot},
{"console", 1, 2, option_console},
@ -137,6 +140,7 @@ static const struct flag_str_s g_flag_str[] =
{SVC_GENTLE_KILL, "gentle_kill"},
{SVC_REMOVE, "remove"},
{SVC_SIGKILL, "sigkill"},
{SVC_FALLBACK, "fallback"},
{SVC_OVERRIDE, "override"},
};
#endif
@ -260,6 +264,16 @@ static int option_restart_period(FAR struct service_manager_s *sm,
return 0;
}
static int option_fallback(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);
add_flags(s, SVC_FALLBACK);
return 0;
}
static int option_override(FAR struct service_manager_s *sm,
int argc, FAR char **argv)
{
@ -768,17 +782,31 @@ int init_service_check(FAR const struct parser_s *parser)
{
if (!strcmp(s->argv[1], tmp->argv[1]))
{
if (!check_flags(tmp, SVC_OVERRIDE))
if (check_flags(tmp, SVC_OVERRIDE))
{
init_info("override: remove old service '%s'",
s->argv[1]);
add_flags(s, SVC_DISABLED | SVC_REMOVE);
}
else if (check_flags(tmp, SVC_FALLBACK))
{
init_info("fallback: ignore new service '%s'",
tmp->argv[1]);
add_flags(tmp, SVC_DISABLED | SVC_REMOVE);
}
else if (check_flags(s, SVC_FALLBACK))
{
init_info("fallback: replace old service '%s'",
s->argv[1]);
add_flags(s, SVC_DISABLED | SVC_REMOVE);
}
else
{
init_err("Redefined service '%s'", tmp->argv[1]);
init_dump_service(s);
init_dump_service(tmp);
return -EEXIST;
}
init_info("Remove duplicate definition of service '%s'",
tmp->argv[1]);
add_flags(s, SVC_DISABLED | SVC_REMOVE);
}
}
}

View file

@ -55,6 +55,10 @@
/* Flags below are new added.
*/
/* Fallback: silently ignored if a service with the same name exists */
#define SVC_FALLBACK (1 << 28)
/* Override the previous definition for a service with the same name */
#define SVC_OVERRIDE (1 << 29)