|
|
1ff636 |
From 8946c35e525c2a14b12ed425f11af152e37d8583 Mon Sep 17 00:00:00 2001
|
|
|
1ff636 |
From: Michal Sekletar <msekleta@redhat.com>
|
|
|
1ff636 |
Date: Fri, 10 Apr 2015 15:56:52 +0200
|
|
|
1ff636 |
Subject: [PATCH] bus-util: be more verbose if dbus job fails
|
|
|
1ff636 |
|
|
|
1ff636 |
Users might have hard time figuring out why exactly their systemctl request
|
|
|
1ff636 |
failed. If dbus job fails try to figure out more details about failure by
|
|
|
1ff636 |
examining Result property of the service.
|
|
|
1ff636 |
|
|
|
1ff636 |
https://bugzilla.redhat.com/show_bug.cgi?id=1016680
|
|
|
1ff636 |
|
|
|
1ff636 |
Cherry-picked from: d5cad22109749faffb7563e4b2a3a728486d47b5
|
|
|
1ff636 |
Resolves: #1016680
|
|
|
1ff636 |
---
|
|
|
23b3cf |
src/libsystemd/sd-bus/bus-util.c | 79 +++++++++++++++++++++++++++++---
|
|
|
1ff636 |
1 file changed, 72 insertions(+), 7 deletions(-)
|
|
|
1ff636 |
|
|
|
1ff636 |
diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
|
|
|
181b3f |
index b0a5a7592..2e6d88962 100644
|
|
|
1ff636 |
--- a/src/libsystemd/sd-bus/bus-util.c
|
|
|
1ff636 |
+++ b/src/libsystemd/sd-bus/bus-util.c
|
|
|
1ff636 |
@@ -30,6 +30,7 @@
|
|
|
1ff636 |
#include "path-util.h"
|
|
|
1ff636 |
#include "missing.h"
|
|
|
1ff636 |
#include "set.h"
|
|
|
1ff636 |
+#include "unit-name.h"
|
|
|
1ff636 |
|
|
|
1ff636 |
#include "sd-bus.h"
|
|
|
1ff636 |
#include "bus-error.h"
|
|
|
1ff636 |
@@ -1690,6 +1691,68 @@ static int bus_process_wait(sd_bus *bus) {
|
|
|
1ff636 |
}
|
|
|
1ff636 |
}
|
|
|
1ff636 |
|
|
|
1ff636 |
+static int bus_job_get_service_result(BusWaitForJobs *d, char **result) {
|
|
|
1ff636 |
+ _cleanup_free_ char *dbus_path = NULL;
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ assert(d);
|
|
|
1ff636 |
+ assert(d->name);
|
|
|
1ff636 |
+ assert(result);
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ dbus_path = unit_dbus_path_from_name(d->name);
|
|
|
1ff636 |
+ if (!dbus_path)
|
|
|
1ff636 |
+ return -ENOMEM;
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ return sd_bus_get_property_string(d->bus,
|
|
|
1ff636 |
+ "org.freedesktop.systemd1",
|
|
|
1ff636 |
+ dbus_path,
|
|
|
1ff636 |
+ "org.freedesktop.systemd1.Service",
|
|
|
1ff636 |
+ "Result",
|
|
|
1ff636 |
+ NULL,
|
|
|
1ff636 |
+ result);
|
|
|
1ff636 |
+}
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+static const struct {
|
|
|
1ff636 |
+ const char *result, *explanation;
|
|
|
1ff636 |
+} explanations [] = {
|
|
|
1ff636 |
+ { "resources", "configured resource limit was exceeded" },
|
|
|
1ff636 |
+ { "timeout", "timeout was exceeded" },
|
|
|
1ff636 |
+ { "exit-code", "control process exited with error code" },
|
|
|
1ff636 |
+ { "signal", "fatal signal was delivered to the control process" },
|
|
|
1ff636 |
+ { "core-dump", "fatal signal was delivered to the control process. Core dumped" },
|
|
|
1ff636 |
+ { "watchdog", "service failed to send watchdog ping" },
|
|
|
1ff636 |
+ { "start-limit", "start of the service was attempted too often too quickly" }
|
|
|
1ff636 |
+};
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+static void log_job_error_with_service_result(const char* service, const char *result) {
|
|
|
1ff636 |
+ unsigned i;
|
|
|
1ff636 |
+ _cleanup_free_ char *service_shell_quoted = NULL;
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ assert(service);
|
|
|
1ff636 |
+ assert(result);
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ service_shell_quoted = shell_maybe_quote(service);
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ for (i = 0; i < ELEMENTSOF(explanations); ++i)
|
|
|
1ff636 |
+ if (streq(result, explanations[i].result))
|
|
|
1ff636 |
+ break;
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ if (i < ELEMENTSOF(explanations))
|
|
|
1ff636 |
+ log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
|
|
|
1ff636 |
+ service,
|
|
|
1ff636 |
+ explanations[i].explanation,
|
|
|
1ff636 |
+ strna(service_shell_quoted));
|
|
|
1ff636 |
+ else
|
|
|
1ff636 |
+ log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
|
|
|
1ff636 |
+ service,
|
|
|
1ff636 |
+ strna(service_shell_quoted));
|
|
|
1ff636 |
+
|
|
|
1ff636 |
+ /* For some results maybe additional explanation is required */
|
|
|
1ff636 |
+ if (streq_ptr(result, "start-limit"))
|
|
|
1ff636 |
+ log_info("To force a start please invoke \"systemctl reset-failed %s\" followed by \"systemctl start %s\" again.",
|
|
|
1ff636 |
+ strna(service_shell_quoted),
|
|
|
1ff636 |
+ strna(service_shell_quoted));
|
|
|
1ff636 |
+}
|
|
|
1ff636 |
+
|
|
|
1ff636 |
static int check_wait_response(BusWaitForJobs *d, bool quiet) {
|
|
|
1ff636 |
int r = 0;
|
|
|
1ff636 |
|
|
|
1ff636 |
@@ -1709,15 +1772,17 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet) {
|
|
|
1ff636 |
else if (streq(d->result, "unsupported"))
|
|
|
1ff636 |
log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
|
|
|
1ff636 |
else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
|
|
|
1ff636 |
- _cleanup_free_ char *quoted = NULL;
|
|
|
1ff636 |
+ if (d->name) {
|
|
|
1ff636 |
+ int q;
|
|
|
1ff636 |
+ _cleanup_free_ char *result = NULL;
|
|
|
1ff636 |
|
|
|
1ff636 |
- if (d->name)
|
|
|
1ff636 |
- quoted = shell_maybe_quote(d->name);
|
|
|
1ff636 |
+ q = bus_job_get_service_result(d, &result);
|
|
|
1ff636 |
+ if (q < 0)
|
|
|
1ff636 |
+ log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name);
|
|
|
1ff636 |
|
|
|
1ff636 |
- if (quoted)
|
|
|
1ff636 |
- log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xe' for details.", d->name, quoted);
|
|
|
1ff636 |
- else
|
|
|
1ff636 |
- log_error("Job failed. See 'journalctl -xe' for details.");
|
|
|
1ff636 |
+ log_job_error_with_service_result(d->name, result);
|
|
|
1ff636 |
+ } else
|
|
|
1ff636 |
+ log_error("Job failed. See \"journalctl -xe\" for details.");
|
|
|
1ff636 |
}
|
|
|
1ff636 |
}
|
|
|
1ff636 |
|