From 9d4cc8e933fc5aa59de995ca51d26cdd5014fcb9 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 16 Aug 2026 12:28:58 +0200 Subject: [PATCH] service: one owner for user-requested start/stop/restart The D-Bus methods carried byte-for-byte copies of api.c's static start/stop/restart helpers. Promote them to service.c alongside service_reload(), which already serves both callers, and reduce both sides to svc_parse_jobstr-style adapters. Signed-off-by: Joachim Wiberg --- src/api.c | 42 +++--------------------------- src/dbus.c | 49 +++++++++-------------------------- src/service.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/service.h | 3 +++ 4 files changed, 90 insertions(+), 75 deletions(-) diff --git a/src/api.c b/src/api.c index e82510a5..a3fdb5a3 100644 --- a/src/api.c +++ b/src/api.c @@ -61,53 +61,19 @@ static int call(int (*action)(svc_t *, void *), char *buf, size_t len) static int stop(svc_t *svc, void *user_data) { (void)user_data; - - if (!svc) - return 1; - - service_timeout_cancel(svc); - svc_stop(svc); - service_step(svc); - if (!IS_RESERVED_RUNLEVEL(runlevel)) - service_step_all(SVC_TYPE_ANY); - - return 0; + return service_stop_now(svc); } static int start(svc_t *svc, void *user_data) { (void)user_data; - - if (!svc) - return 1; - - service_timeout_cancel(svc); - svc_start(svc); - service_step(svc); - if (!IS_RESERVED_RUNLEVEL(runlevel)) - service_step_all(SVC_TYPE_ANY); - - return 0; + return service_start_now(svc); } -/* - * NOTE: this does not wait for svc to be stopped first, that is the - * responsibility of initctl to do. Otherwise we'd block PID 1, - * or introduce some nasty race conditions. - */ static int restart(svc_t *svc, void *user_data) { - if (!svc) - return 1; - - if (!svc_is_running(svc)) - return start(svc, user_data); - - service_timeout_cancel(svc); - service_stop(svc); - service_step(svc); - - return 0; + (void)user_data; + return service_restart_now(svc); } static int reload(svc_t *svc, void *user_data) diff --git a/src/dbus.c b/src/dbus.c index 389f0d14..f828289c 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -314,46 +314,24 @@ static int manager_get_service(link_call_t *call, void *userdata) return 0; } -/* Service-control helpers used by Start/Stop/Restart/Reload. These - * mirror the static helpers in api.c — kept private here so api.c - * stays untouched in this increment. */ +/* svc_parse_jobstr-style adapters over the shared service helpers */ static int dbus_apply_stop(svc_t *svc, void *user_data) { (void)user_data; - if (!svc) - return 1; - service_timeout_cancel(svc); - svc_stop(svc); - service_step(svc); - if (!IS_RESERVED_RUNLEVEL(runlevel)) - service_step_all(SVC_TYPE_ANY); - return 0; + return service_stop_now(svc); } static int dbus_apply_start(svc_t *svc, void *user_data) { (void)user_data; - if (!svc) - return 1; - service_timeout_cancel(svc); - svc_start(svc); - service_step(svc); - if (!IS_RESERVED_RUNLEVEL(runlevel)) - service_step_all(SVC_TYPE_ANY); - return 0; + return service_start_now(svc); } static int dbus_apply_restart(svc_t *svc, void *user_data) { - if (!svc) - return 1; - if (!svc_is_running(svc)) - return dbus_apply_start(svc, user_data); - service_timeout_cancel(svc); - service_stop(svc); - service_step(svc); - return 0; + (void)user_data; + return service_restart_now(svc); } struct dispatch_ctx { @@ -685,18 +663,15 @@ static int service1_start (link_call_t *c, void *u) { return service_action_met static int service1_stop (link_call_t *c, void *u) { return service_action_method(c, u, dbus_apply_stop); } static int service1_restart(link_call_t *c, void *u) { return service_action_method(c, u, dbus_apply_restart); } -static int service1_reload(link_call_t *call, void *userdata) +static int dbus_apply_reload(svc_t *svc, void *user_data) { - svc_t *svc = userdata; + (void)user_data; + return service_reload(svc); +} - if (!svc) - return link_call_reply_error(call, - "org.finit.Error.NoSuchService", - "Service object no longer valid"); - - service_reload(svc); - (void)link_call_reply(call); - return 0; +static int service1_reload(link_call_t *c, void *u) +{ + return service_action_method(c, u, dbus_apply_reload); } static const link_method_t service_methods[] = { diff --git a/src/service.c b/src/service.c index 3c2e05f4..e13d5199 100644 --- a/src/service.c +++ b/src/service.c @@ -1442,6 +1442,77 @@ int service_stop(svc_t *svc) return rc; } +/** + * service_stop_now - Stop a service on user request + * @svc: Service to stop + * + * Shared by the legacy API and the D-Bus methods, like + * service_reload(). + * + * Returns: + * POSIX OK(0) on success, non-zero if @svc is NULL. + */ +int service_stop_now(svc_t *svc) +{ + if (!svc) + return 1; + + service_timeout_cancel(svc); + svc_stop(svc); + service_step(svc); + if (!IS_RESERVED_RUNLEVEL(runlevel)) + service_step_all(SVC_TYPE_ANY); + + return 0; +} + +/** + * service_start_now - Start a service on user request + * @svc: Service to start + * + * Returns: + * POSIX OK(0) on success, non-zero if @svc is NULL. + */ +int service_start_now(svc_t *svc) +{ + if (!svc) + return 1; + + service_timeout_cancel(svc); + svc_start(svc); + service_step(svc); + if (!IS_RESERVED_RUNLEVEL(runlevel)) + service_step_all(SVC_TYPE_ANY); + + return 0; +} + +/** + * service_restart_now - Restart a service on user request + * @svc: Service to restart + * + * Does not wait for @svc to stop first, that is the caller's + * (initctl) responsibility. Otherwise we'd block PID 1, or + * introduce some nasty race conditions. + * + * Returns: + * POSIX OK(0) on success, non-zero if @svc is NULL. + */ +int service_restart_now(svc_t *svc) +{ + if (!svc) + return 1; + + if (!svc_is_running(svc)) + return service_start_now(svc); + + service_timeout_cancel(svc); + service_stop(svc); + service_step(svc); + + return 0; +} + /** * service_reload - Request reload of a service, driven by the state machine * @svc: Service to reload diff --git a/src/service.h b/src/service.h index 59699f3f..efea5a85 100644 --- a/src/service.h +++ b/src/service.h @@ -60,6 +60,9 @@ void service_forked (svc_t *svc); void service_ready (svc_t *svc, int ready); int service_stop (svc_t *svc); +int service_start_now (svc_t *svc); +int service_stop_now (svc_t *svc); +int service_restart_now (svc_t *svc); int service_reload (svc_t *svc); int service_step (svc_t *svc); void service_step_all (int types);