unit_start: Make unit actions asynchronous 80/205480/3
authorPaweł Szewczyk <p.szewczyk@samsung.com>
Mon, 6 May 2019 13:20:32 +0000 (15:20 +0200)
committerPaweł Szewczyk <p.szewczyk@samsung.com>
Thu, 16 May 2019 09:44:57 +0000 (11:44 +0200)
The response from systemd can be delayed resulting in blocking of the
event processor. We can prevent this by making actions on units
asynchronous.

Change-Id: I175420639820da9ae0a2b0bf4e2a817a68a5fa76
Signed-off-by: Paweł Szewczyk <p.szewczyk@samsung.com>
include/systemd_dbus.h
src/action/unit_start.c
src/util/systemd_dbus.c

index 3e004768091be9e9b2622a4851c32b0990d2aaab..f248a090df53c31306e9c6a69a855748ad9706fc 100644 (file)
@@ -42,6 +42,19 @@ int epc_dbus_call(char *service, char *obj, char *interface, char *method,
        epc_dbus_call_simple(SYSTEMD_SERVICE, OBJ, INTF, METHOD,                  \
                                                        ARGS, ##__VA_ARGS__)
 
+typedef sd_bus_message_handler_t epc_dbus_handler_t;
+
+int epc_dbus_call_async(char *service, char *obj, char *interface, char *method,
+                                        sd_bus_error *error, epc_dbus_handler_t cb,
+                                        void *user_data, char *args, ...);
+
+#define epc_dbus_call_simple_async(SRV, OBJ, INTF, METHOD, CB, DATA, ARGS, ...)        \
+       epc_dbus_call_async(SRV, OBJ, INTF, METHOD, NULL, CB, DATA, ARGS, ##__VA_ARGS__)
+
+#define epc_dbus_call_systemd_simple_async(OBJ, INTF, METHOD, CB, DATA, ARGS, ...) \
+       epc_dbus_call_simple_async(SYSTEMD_SERVICE, OBJ, INTF, METHOD, CB, DATA,          \
+                                                       ARGS, ##__VA_ARGS__)
+
 int epc_acquire_systemd_bus(sd_bus **bus);
 void epc_set_systemd_private(bool);
 
index ea2853e0bb5ce447f40d2d8dda182bd111aa8d88..21bbd920955c3935a1ea635ecb6b57b940a3d208 100644 (file)
 #include "systemd_dbus.h"
 #include "common.h"
 
+static int unit_action_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error)
+{
+       struct action_executed_event *exe_info = userdata;
+       int ret;
+
+       if (!exe_info)
+               return -EINVAL;
+
+       exe_info->result = 0;
+       ret = event_processor_report_event(&exe_info->event);
+       epc_event_unref(&exe_info->event);
+
+       return ret;
+}
+
 static int start_unit(struct epc_action *action,
                struct action_executed_event *exe_info)
 {
@@ -66,9 +81,11 @@ static int start_unit(struct epc_action *action,
                return 0;
        }
 
-       ret = epc_dbus_call_systemd_simple(SYSTEMD_OBJ,
+       ret = epc_dbus_call_systemd_simple_async(SYSTEMD_OBJ,
                        SYSTEMD_MANAGER_INTERFACE,
                        unit_action,
+                       unit_action_handler,
+                       exe_info,
                        "ss",
                        unit_name,
                        "replace");
@@ -78,7 +95,8 @@ static int start_unit(struct epc_action *action,
        else
                log_kmsg("Starting unit: %s", unit_name);
 
-       exe_info->result = ret;
+       exe_info->result = -EPROBE_DEFER;
+       epc_event_ref(&exe_info->event);
        return 0;
 }
 
index fe3d2b523c77f3279d45f1d0c41e1df69c70fc0c..f632e1257541af12088c2b0ce3e4c21fbb5ae6da 100644 (file)
 static sd_bus *systemd_bus = NULL;
 static bool epc_systemd_private = false;
 
+int epc_dbus_call_async(char *service, char *obj, char *interface, char *method,
+                                        sd_bus_error *error, epc_dbus_handler_t cb,
+                                        void *user_data, char *types, ...)
+{
+       _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+       _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+       int ret;
+
+       ret = epc_acquire_systemd_bus(&bus);
+       if (ret < 0)
+               return ret;
+
+       ret = sd_bus_message_new_method_call(bus, &m, service, obj, interface, method);
+       if (ret < 0)
+               goto fail;
+
+       if (types) {
+               va_list args;
+
+               va_start(args, types);
+               ret = sd_bus_message_appendv(m, types, args);
+               va_end(args);
+               if (ret < 0)
+                       goto fail;
+       }
+
+       return sd_bus_call_async(bus, NULL, m, cb, user_data, 0);
+
+fail:
+       return ret;
+}
+
 int epc_dbus_call(char *service, char *obj, char *interface, char *method,
                                         sd_bus_error *error, sd_bus_message **out_msg,
                                         char *types, ...)