diff options
author | Maciej Slodczyk <m.slodczyk2@partner.samsung.com> | 2019-05-27 09:13:27 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@review.ap-northeast-2.compute.internal> | 2019-05-27 09:13:27 +0000 |
commit | 5822cf503c119b263c058dd550e3985ba6c38af8 (patch) | |
tree | 20e29f37f2c180c046146cb649df3aca4ad04b50 | |
parent | d8a35df8fff2f1321c0ceaffb3fd8e0f903d5997 (diff) | |
parent | 0f46414396a1d1efe7bb4c0401057d5dabf0f231 (diff) | |
download | activationd-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.c | 106 |
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; } |