From: John Crispin Date: Fri, 12 Nov 2021 18:59:29 +0000 (+0100) Subject: procd: add full service shutdown prior to sysupgrade X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=87b583635475c56ae5b8ec89233f6f292ba09765;p=project%2Fprocd.git procd: add full service shutdown prior to sysupgrade Currently OpenWrt will use the kill loop in stage2 to stop tasks. This can fail as seen with wpa_supplicant not properly shutting down with certain mesh configurations. Trigger the existing service_stop() code path for all services just before exec'ing to upgraded. Signed-off-by: John Crispin [make use of *_safe function now introduced for that purpose, also stop container instances] Signed-off-by: Daniel Golle --- diff --git a/service/service.c b/service/service.c index 48825c3..5c66fb2 100644 --- a/service/service.c +++ b/service/service.c @@ -653,6 +653,34 @@ service_handle_state(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_OK; } +static void +service_avl_stop_all(struct avl_tree *sctree, unsigned int *term_timeout) +{ + struct service *s; + + avl_for_each_element(sctree, s, avl) { + struct service_instance *in, *ptr; + + vlist_for_each_element_safe(&s->instances, in, node, ptr) { + if (in->term_timeout > *term_timeout) + *term_timeout = in->term_timeout; + instance_stop(in, true); + } + } +} + +void +service_stop_all(void) +{ + unsigned int term_timeout = 0; + + service_avl_stop_all(&containers, &term_timeout); + service_avl_stop_all(&services, &term_timeout); + /* ToDo: inittab */ + + sleep(term_timeout); +} + static int service_handle_update(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, diff --git a/service/service.h b/service/service.h index e148369..6ddc04e 100644 --- a/service/service.h +++ b/service/service.h @@ -60,6 +60,7 @@ int service_start_early(char *name, char *cmdline, char *user, char *group); void service_stopped(struct service *s); void service_validate_del(struct service *s); void service_event(const char *type, const char *service, const char *instance); +void service_stop_all(void); diff --git a/system.c b/system.c index 5811d39..93eac59 100644 --- a/system.c +++ b/system.c @@ -33,6 +33,7 @@ #include "procd.h" #include "sysupgrade.h" #include "watchdog.h" +#include "service/service.h" static struct blob_buf b; static int notify; @@ -810,6 +811,8 @@ static int sysupgrade(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_NOT_SUPPORTED; } + service_stop_all(); + sysupgrade_exec_upgraded(blobmsg_get_string(tb[SYSUPGRADE_PREFIX]), blobmsg_get_string(tb[SYSUPGRADE_PATH]), tb[SYSUPGRADE_BACKUP] ? blobmsg_get_string(tb[SYSUPGRADE_BACKUP]) : NULL,