cc232e9
From c45e0321f16a6d13ab510d1594c2a90639dcb96a Mon Sep 17 00:00:00 2001
cc232e9
From: Michal Sekletar <msekleta@redhat.com>
cc232e9
Date: Wed, 13 Jun 2012 14:14:13 +0200
cc232e9
Subject: [PATCH] systemctl will print warning when stopping unit
cc232e9
cc232e9
systemctl now prints warning and list of sockets in listenning state which can
cc232e9
trigger start of service which is about to be stopped
cc232e9
(cherry picked from commit 701cdcb9ee846b3d1629b55a11c61a3343af4874)
cc232e9
---
cc232e9
 src/systemctl/systemctl.c |  233 +++++++++++++++++++++++++++++++++++++++++++++
cc232e9
 1 file changed, 233 insertions(+)
cc232e9
cc232e9
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
cc232e9
index ed3dbab..a38d799 100644
cc232e9
--- a/src/systemctl/systemctl.c
cc232e9
+++ b/src/systemctl/systemctl.c
cc232e9
@@ -1480,6 +1480,234 @@ finish:
cc232e9
         return r;
cc232e9
 }
cc232e9
 
cc232e9
+static int get_unit_path(
cc232e9
+                DBusConnection *bus,
cc232e9
+                DBusError *error,
cc232e9
+                const char *name,
cc232e9
+                char **unit_path) {
cc232e9
+
cc232e9
+        DBusMessage *m = NULL, *reply = NULL;
cc232e9
+        int r = 0;
cc232e9
+
cc232e9
+        assert(bus);
cc232e9
+        assert(error);
cc232e9
+        assert(name);
cc232e9
+        assert(unit_path);
cc232e9
+
cc232e9
+        *unit_path = NULL;
cc232e9
+
cc232e9
+
cc232e9
+        m = dbus_message_new_method_call("org.freedesktop.systemd1",
cc232e9
+                                         "/org/freedesktop/systemd1",
cc232e9
+                                         "org.freedesktop.systemd1.Manager",
cc232e9
+                                         "GetUnit");
cc232e9
+        if (!m) {
cc232e9
+                log_error("Could not allocate message.");
cc232e9
+                r = -ENOMEM;
cc232e9
+                goto finish;
cc232e9
+        }
cc232e9
+
cc232e9
+        if (!dbus_message_append_args(m,
cc232e9
+                                DBUS_TYPE_STRING, &name,
cc232e9
+                                DBUS_TYPE_INVALID)) {
cc232e9
+                log_error("Could not append arguments to message.");
cc232e9
+                r = -ENOMEM;
cc232e9
+                goto finish;
cc232e9
+        }
cc232e9
+
cc232e9
+        reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error);
cc232e9
+        if (!reply) {
cc232e9
+                if (streq(error->name, BUS_ERROR_NO_SUCH_UNIT)) {
cc232e9
+                        dbus_error_free(error);
cc232e9
+                        r = -EINVAL;
cc232e9
+                } else {
cc232e9
+                        log_error("Failed to issue method call: %s", bus_error_message(error));
cc232e9
+                        r = -EIO;
cc232e9
+                }
cc232e9
+                goto finish;
cc232e9
+        }
cc232e9
+
cc232e9
+        if (!dbus_message_get_args(reply, error,
cc232e9
+                                DBUS_TYPE_OBJECT_PATH, unit_path,
cc232e9
+                                DBUS_TYPE_INVALID)) {
cc232e9
+                log_error("Failed to parse reply: %s", bus_error_message(error));
cc232e9
+                r = -EIO;
cc232e9
+                goto finish;
cc232e9
+        }
cc232e9
+
cc232e9
+        *unit_path = strdup(*unit_path);
cc232e9
+        if (!(*unit_path)) {
cc232e9
+               log_error("Failed to duplicate unit path");
cc232e9
+               r = -ENOMEM;
cc232e9
+        }
cc232e9
+finish:
cc232e9
+        if (m)
cc232e9
+                dbus_message_unref(m);
cc232e9
+        if (reply)
cc232e9
+                dbus_message_unref(reply);
cc232e9
+        return r;
cc232e9
+}
cc232e9
+
cc232e9
+static int is_socket_listening(
cc232e9
+                DBusConnection *bus,
cc232e9
+                DBusError *error,
cc232e9
+                const char *socket_name) {
cc232e9
+
cc232e9
+        DBusMessage *m = NULL, *reply = NULL;
cc232e9
+        DBusMessageIter iter, sub;
cc232e9
+        char *socket_object_path = NULL;
cc232e9
+        const char *sub_state = NULL,
cc232e9
+                   *interface = "org.freedesktop.systemd1.Unit",
cc232e9
+                   *property = "SubState";
cc232e9
+        int r = 0;
cc232e9
+
cc232e9
+        assert(bus);
cc232e9
+        assert(error);
cc232e9
+        assert(socket_name);
cc232e9
+
cc232e9
+        if ((r = get_unit_path(bus, error, socket_name, &socket_object_path)) < 0) {
cc232e9
+                goto finish;
cc232e9
+        }
cc232e9
+        m = dbus_message_new_method_call("org.freedesktop.systemd1",
cc232e9
+                                         socket_object_path,
cc232e9
+                                         "org.freedesktop.DBus.Properties",
cc232e9
+                                         "Get");
cc232e9
+        if (!m) {
cc232e9
+                log_error("Could not allocate message.");
cc232e9
+                r = -ENOMEM;
cc232e9
+                goto finish;
cc232e9
+        }
cc232e9
+
cc232e9
+        if (!dbus_message_append_args(m,
cc232e9
+                                DBUS_TYPE_STRING, &interface,
cc232e9
+                                DBUS_TYPE_STRING, &property,
cc232e9
+                                DBUS_TYPE_INVALID)) {
cc232e9
+                log_error("Could not append arguments to message.");
cc232e9
+                r = -ENOMEM;
cc232e9
+                goto finish;
cc232e9
+        }
cc232e9
+
cc232e9
+        reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error);
cc232e9
+        if (!reply) {
cc232e9
+                log_error("Failed to issue method call: %s", bus_error_message(error));
cc232e9
+                r = -EIO;
cc232e9
+                goto finish;
cc232e9
+        }
cc232e9
+
cc232e9
+        dbus_message_iter_init(reply, &iter);
cc232e9
+        dbus_message_iter_recurse(&iter, &sub);
cc232e9
+
cc232e9
+        if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
cc232e9
+                log_error("Failed to parse reply: %s", bus_error_message(error));
cc232e9
+                r = -EIO;
cc232e9
+                goto finish;
cc232e9
+        }
cc232e9
+        dbus_message_iter_get_basic(&sub, &sub_state);
cc232e9
+        r = streq(sub_state, "listening");
cc232e9
+finish:
cc232e9
+        if (m)
cc232e9
+                dbus_message_unref(m);
cc232e9
+
cc232e9
+        if (reply)
cc232e9
+                dbus_message_unref(reply);
cc232e9
+
cc232e9
+        free(socket_object_path);
cc232e9
+        return r;
cc232e9
+}
cc232e9
+
cc232e9
+static void check_listening_sockets(
cc232e9
+                DBusConnection *bus,
cc232e9
+                DBusError *error,
cc232e9
+                const char *unit_name) {
cc232e9
+
cc232e9
+        DBusMessage *m = NULL, *reply = NULL;
cc232e9
+        DBusMessageIter iter, sub;
cc232e9
+        const char *service_trigger = NULL,
cc232e9
+                   *interface = "org.freedesktop.systemd1.Unit",
cc232e9
+                   *triggered_by_property = "TriggeredBy";
cc232e9
+
cc232e9
+        char *unit_path = NULL;
cc232e9
+        int print_warning_label = 1;
cc232e9
+
cc232e9
+        if ((get_unit_path(bus, error, unit_name, &unit_path) < 0)) {
cc232e9
+                goto finish;
cc232e9
+        }
cc232e9
+
cc232e9
+        m = dbus_message_new_method_call("org.freedesktop.systemd1",
cc232e9
+                                         unit_path,
cc232e9
+                                         "org.freedesktop.DBus.Properties",
cc232e9
+                                         "Get");
cc232e9
+        if (!m) {
cc232e9
+                log_error("Could not allocate message.");
cc232e9
+                goto finish;
cc232e9
+        }
cc232e9
+
cc232e9
+        if (!dbus_message_append_args(m,
cc232e9
+                                DBUS_TYPE_STRING, &interface,
cc232e9
+                                DBUS_TYPE_STRING, &triggered_by_property,
cc232e9
+                                DBUS_TYPE_INVALID)) {
cc232e9
+                log_error("Could not append arguments to message.");
cc232e9
+                goto finish;
cc232e9
+        }
cc232e9
+
cc232e9
+        reply = dbus_connection_send_with_reply_and_block(bus, m, -1, error);
cc232e9
+        if (!reply) {
cc232e9
+                log_error("Failed to issue method call: %s", bus_error_message(error));
cc232e9
+                goto finish;
cc232e9
+        }
cc232e9
+
cc232e9
+        if (!dbus_message_iter_init(reply, &iter) ||
cc232e9
+                        dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
cc232e9
+                log_error("Failed to parse reply: %s", bus_error_message(error));
cc232e9
+                goto finish;
cc232e9
+
cc232e9
+        }
cc232e9
+
cc232e9
+        dbus_message_iter_recurse(&iter, &sub);
cc232e9
+        dbus_message_iter_recurse(&sub, &iter);
cc232e9
+        sub = iter;
cc232e9
+
cc232e9
+        while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
cc232e9
+                int r = 0;
cc232e9
+
cc232e9
+                if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
cc232e9
+                        log_error("Failed to parse reply: %s", bus_error_message(error));
cc232e9
+                        goto finish;
cc232e9
+                }
cc232e9
+
cc232e9
+                dbus_message_iter_get_basic(&sub, &service_trigger);
cc232e9
+
cc232e9
+                if (endswith(service_trigger, ".socket")) {
cc232e9
+                        r = is_socket_listening(bus, error, service_trigger);
cc232e9
+                } else {
cc232e9
+                        dbus_message_iter_recurse(&iter, &sub);
cc232e9
+                        iter = sub;
cc232e9
+                        continue;
cc232e9
+                }
cc232e9
+
cc232e9
+                if (r == 1) {
cc232e9
+                        if (print_warning_label) {
cc232e9
+                                log_warning("There are listening sockets associated with %s :", unit_name);
cc232e9
+                                print_warning_label = 0;
cc232e9
+                        }
cc232e9
+                        log_warning("%s",service_trigger);
cc232e9
+                } else if (r < 0) {
cc232e9
+                        log_error("Failed to issue function call: %s", bus_error_message(error));
cc232e9
+                        goto finish;
cc232e9
+                }
cc232e9
+                dbus_message_iter_recurse(&iter, &sub);
cc232e9
+                iter = sub;
cc232e9
+        }
cc232e9
+finish:
cc232e9
+        if (m)
cc232e9
+                dbus_message_unref(m);
cc232e9
+
cc232e9
+        if (reply)
cc232e9
+                dbus_message_unref(reply);
cc232e9
+
cc232e9
+        free(unit_path);
cc232e9
+}
cc232e9
+
cc232e9
 static int start_unit_one(
cc232e9
                 DBusConnection *bus,
cc232e9
                 const char *method,
cc232e9
@@ -1560,6 +1788,11 @@ static int start_unit_one(
cc232e9
                 }
cc232e9
         }
cc232e9
 
cc232e9
+        /* When stopping unit check if we have some listening sockets active */
cc232e9
+        if (streq(method, "StopUnit") && !arg_quiet) {
cc232e9
+               check_listening_sockets(bus, error, name);
cc232e9
+        }
cc232e9
+
cc232e9
         r = 0;
cc232e9
 
cc232e9
 finish: