summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaciej Slodczyk <m.slodczyk2@partner.samsung.com>2019-05-27 09:13:27 +0000
committerGerrit Code Review <gerrit@review.ap-northeast-2.compute.internal>2019-05-27 09:13:27 +0000
commit5822cf503c119b263c058dd550e3985ba6c38af8 (patch)
tree20e29f37f2c180c046146cb649df3aca4ad04b50
parentd8a35df8fff2f1321c0ceaffb3fd8e0f903d5997 (diff)
parent0f46414396a1d1efe7bb4c0401057d5dabf0f231 (diff)
downloadactivationd-5822cf503c119b263c058dd550e3985ba6c38af8.tar.gz
activationd-5822cf503c119b263c058dd550e3985ba6c38af8.tar.bz2
activationd-5822cf503c119b263c058dd550e3985ba6c38af8.zip
Merge "unit_start: Optionally wait for job finish" into tizen
-rw-r--r--src/action/unit_start.c106
1 files changed, 85 insertions, 21 deletions
diff --git a/src/action/unit_start.c b/src/action/unit_start.c
index b06ac4d..b01ed9d 100644
--- a/src/action/unit_start.c
+++ b/src/action/unit_start.c
@@ -23,19 +23,78 @@
#include "systemd_dbus.h"
#include "common.h"
+struct unit_action_data {
+ struct action_executed_event *exe_info;
+ bool wait_for_unit;
+ char *job;
+ sd_bus_slot *slot;
+};
+
+static int finish_action(struct unit_action_data *data, int result, const char *err_msg)
+{
+ int ret;
+
+ if (err_msg)
+ epc_object_append_string(data->exe_info->action_log, "error", err_msg);
+
+ data->exe_info->result = result;
+ ret = event_processor_report_event(&data->exe_info->event);
+ epc_event_unref(&data->exe_info->event);
+ free(data);
+
+ return ret;
+}
+
+static int on_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *ret_error)
+{
+ struct unit_action_data *data = userdata;
+ char *job;
+ int ret;
+
+ if (!data)
+ return -EINVAL;
+
+ ret = sd_bus_message_read(m, "uoss", NULL, &job, NULL, NULL);
+ if (ret < 0) {
+ log_error("Could not read JobRemoved signal");
+ return -EINVAL;
+ }
+
+ if (strcmp(data->job, job) == 0)
+ finish_action(data, 0, NULL);
+
+ return 0;
+}
+
static int unit_action_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error)
{
- struct action_executed_event *exe_info = userdata;
+ struct unit_action_data *data = userdata;
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
int ret;
- if (!exe_info)
+ if (!data)
return -EINVAL;
- exe_info->result = 0;
- ret = event_processor_report_event(&exe_info->event);
- epc_event_unref(&exe_info->event);
+ ret = epc_acquire_systemd_bus(&bus);
+ if (ret < 0)
+ return finish_action(data, ret, "Could not acquire systemd bus");
- return ret;
+ if (data->wait_for_unit) {
+ ret = sd_bus_add_match(bus, &data->slot,
+ "type='signal',sender='org.freedesktop.systemd1',"
+ "interface='org.freedesktop.systemd1.Manager',"
+ "member='JobRemoved',"
+ "path_namespace='/org/freedesktop/systemd1'",
+ on_job_removed,
+ data);
+ if (ret < 0) {
+ return finish_action(data, ret, "Could not register for JobRemoved signal");
+ }
+
+ return 0;
+ }
+
+ return finish_action(data, 0, NULL);
}
static int start_unit(struct epc_action *action,
@@ -46,6 +105,7 @@ static int start_unit(struct epc_action *action,
char *unit_name = NULL;
char *unit_action = NULL;
int ret;
+ struct unit_action_data *data;
/*
* We are passing an event to exe_info, so there is no need to unref it
@@ -62,41 +122,45 @@ static int start_unit(struct epc_action *action,
return 0;
}
- epc_object_get_string(dm_ev->action_data,
+ data = malloc(sizeof(*data));
+ if (!data)
+ return -ENOMEM;
+
+ data->exe_info = exe_info;
+
+ ret = epc_object_get_bool(dm_ev->action_data, "wait", &data->wait_for_unit);
+ if (ret < 0)
+ data->wait_for_unit = false;
+
+ ret = epc_object_get_string(dm_ev->action_data,
EPC_AD_UNIT_ACTION, &unit_action);
- if (!unit_action) {
- epc_object_append_string(exe_info->action_log, "error",
- "Unit action not specified");
- exe_info->result = -EINVAL;
- return 0;
- }
+ if (!unit_action)
+ return finish_action(data, -EINVAL, "Unit action not specified");
if (strcmp(unit_action, "StartUnit") &&
strcmp(unit_action, "StopUnit") &&
- strcmp(unit_action, "RestartUnit")) {
- epc_object_append_string(exe_info->action_log, "error",
+ strcmp(unit_action, "RestartUnit"))
+ return finish_action(data, -EINVAL,
"Unit action is not one of \"StartUnit\", "
"\"StopUnit\" or \"RestartUnit\"");
- exe_info->result = -EINVAL;
- return 0;
- }
ret = epc_dbus_call_systemd_simple_async(SYSTEMD_OBJ,
SYSTEMD_MANAGER_INTERFACE,
unit_action,
unit_action_handler,
- exe_info,
+ data,
"ss",
unit_name,
"replace");
if (ret < 0)
- epc_object_append_string(exe_info->action_log, "error",
- "Failed to call systemd");
+ return finish_action(data, ret, "Failed to call systemd");
else
log_kmsg("Starting unit: %s", unit_name);
+ /* The result will be delayed */
exe_info->result = -EPROBE_DEFER;
epc_event_ref(&exe_info->event);
+
return 0;
}