procd: add full service shutdown prior to sysupgrade
authorJohn Crispin <john@phrozen.org>
Fri, 12 Nov 2021 18:59:29 +0000 (19:59 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Tue, 23 Nov 2021 13:56:47 +0000 (13:56 +0000)
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 <john@phrozen.org>
[make use of *_safe function now introduced for that purpose, also stop
container instances]
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
service/service.c
service/service.h
system.c

index 48825c327063dfd0ce860df9e73c95028be2112d..5c66fb21c57ef82bcdfea2d5465beec1dcb1e83a 100644 (file)
@@ -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,
index e148369d3156effb7c1db49af74ad02fc59df909..6ddc04ee3aa60e19957e68e6d493705f64caccd5 100644 (file)
@@ -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);
 
 
 
index 5811d3982a583986f28c3b59783e01945e1f02f4..93eac59c3b01ce3729dc27539ac483f5314759d3 100644 (file)
--- 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,