Sometimes stage2 is unable to kill all processes which results in a
failed upgrade.

Rather than fully relying on stage2, let procd gracefully terminate
the services in the services AVL tree before handing control to
upgraded.

Signed-off-by: Daniel Bailey <[email protected]>
---
 service/service.c | 22 ++++++++++++++++++++++
 service/service.h |  1 +
 system.c          |  6 ++++++
 3 files changed, 29 insertions(+)

diff --git a/service/service.c b/service/service.c
index fcf0215..7191cec 100644
--- a/service/service.c
+++ b/service/service.c
@@ -837,6 +837,28 @@ service_start_early(char *name, char *cmdline)
        return service_handle_set(NULL, NULL, NULL, "add", b.head);
 }
 
+int
+service_delete_all(void)
+{
+       struct service *s, *safe;
+       const struct avl_tree *tree = &services;
+       int ret;
+
+       avl_for_each_element_safe(tree, s, avl, safe) {
+               blob_buf_init(&b, 0);
+               blobmsg_add_string(&b, "name", s->name);
+
+               ret = service_handle_delete(NULL, NULL, NULL, NULL, b.head);
+
+               if (ret) {
+                       ERROR("failed to delete service '%s'", s->name);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
 void service_stopped(struct service *s)
 {
        _service_stopped(s, false);
diff --git a/service/service.h b/service/service.h
index fac5da9..09ed409 100644
--- a/service/service.h
+++ b/service/service.h
@@ -56,6 +56,7 @@ void service_validate_add(struct service *s, struct blob_attr 
*attr);
 void service_validate_dump(struct blob_buf *b, struct service *s);
 void service_validate_dump_all(struct blob_buf *b, char *p, char *s);
 int service_start_early(char *name, char *cmdline);
+int service_delete_all(void);
 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);
diff --git a/system.c b/system.c
index 0fb98f1..38a0539 100644
--- a/system.c
+++ b/system.c
@@ -30,6 +30,7 @@
 #include <libubox/uloop.h>
 
 #include "procd.h"
+#include "service/service.h"
 #include "sysupgrade.h"
 #include "watchdog.h"
 
@@ -695,6 +696,11 @@ static int sysupgrade(struct ubus_context *ctx, struct 
ubus_object *obj,
                return UBUS_STATUS_NOT_SUPPORTED;
        }
 
+       if (service_delete_all()) {
+               sysupgrade_error(ctx, req, "Failed to delete all services");
+               return UBUS_STATUS_UNKNOWN_ERROR;
+       }
+
        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,
-- 
2.25.1


_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to