84b277
From 4323a5406bb40c76076814fd998e09c58b433e7d Mon Sep 17 00:00:00 2001
84b277
From: Miguel Angel Ajo <mangelajo@redhat.com>
84b277
Date: Mon, 7 Jul 2014 14:20:36 +0200
84b277
Subject: [PATCH] core: Added support for ERRNO NOTIFY_SOCKET  message parsing
84b277
84b277
Added StatusErrno dbus property along StatusText to allow notification of
84b277
numeric status condition while degraded service operation or any other special
84b277
situation.
84b277
84b277
(cherry picked from commit 4774e357268e4a1e9fa82adb0563a538932a4c8e)
84b277
84b277
Resolves: #1106457
84b277
---
84b277
 src/core/dbus-service.c |  3 +++
84b277
 src/core/service.c      | 33 +++++++++++++++++++++++++++++----
84b277
 src/core/service.h      |  1 +
84b277
 3 files changed, 33 insertions(+), 4 deletions(-)
84b277
84b277
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
84b277
index 696c446..edfc7ff 100644
84b277
--- a/src/core/dbus-service.c
84b277
+++ b/src/core/dbus-service.c
84b277
@@ -64,6 +64,7 @@
84b277
         "  <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
84b277
         "  <property name=\"BusName\" type=\"s\" access=\"read\"/>\n"   \
84b277
         "  <property name=\"StatusText\" type=\"s\" access=\"read\"/>\n" \
84b277
+        "  <property name=\"StatusErrno\" type=\"i\" access=\"read\"/>\n" \
84b277
         "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
84b277
        " </interface>\n"
84b277
 
84b277
@@ -96,6 +97,7 @@ const char bus_service_invalidating_properties[] =
84b277
         "MainPID\0"
84b277
         "ControlPID\0"
84b277
         "StatusText\0"
84b277
+        "StatusErrno\0"
84b277
         "Result\0";
84b277
 
84b277
 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_type, service_type, ServiceType);
84b277
@@ -144,6 +146,7 @@ static const BusProperty bus_service_properties[] = {
84b277
         { "ControlPID",             bus_property_append_pid,          "u", offsetof(Service, control_pid)                  },
84b277
         { "BusName",                bus_property_append_string,       "s", offsetof(Service, bus_name),               true },
84b277
         { "StatusText",             bus_property_append_string,       "s", offsetof(Service, status_text),            true },
84b277
+        { "StatusErrno",            bus_property_append_int,          "i", offsetof(Service, status_errno)                 },
84b277
         { "Result",                 bus_service_append_service_result,"s", offsetof(Service, result)                       },
84b277
         {}
84b277
 };
84b277
diff --git a/src/core/service.c b/src/core/service.c
84b277
index f6fdbbc..3f6c8ac 100644
84b277
--- a/src/core/service.c
84b277
+++ b/src/core/service.c
84b277
@@ -3443,6 +3443,7 @@ static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) {
84b277
 static void service_notify_message(Unit *u, pid_t pid, char **tags) {
84b277
         Service *s = SERVICE(u);
84b277
         const char *e;
84b277
+        bool notify_dbus = false;
84b277
 
84b277
         assert(u);
84b277
 
84b277
@@ -3478,6 +3479,7 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) {
84b277
                                        "%s: got %s", u->id, e);
84b277
                         service_set_main_pid(s, pid);
84b277
                         unit_watch_pid(UNIT(s), pid);
84b277
+                        notify_dbus = true;
84b277
                 }
84b277
         }
84b277
 
84b277
@@ -3516,12 +3518,34 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) {
84b277
 
84b277
                         free(s->status_text);
84b277
                         s->status_text = t;
84b277
-                } else {
84b277
+                } else
84b277
+                        t = NULL;
84b277
+
84b277
+                if (!streq_ptr(s->status_text, t)) {
84b277
                         free(s->status_text);
84b277
-                        s->status_text = NULL;
84b277
-                }
84b277
+                        s->status_text = t;
84b277
+                        notify_dbus = true;
84b277
+                } else
84b277
+                        free(t);
84b277
+        }
84b277
+
84b277
+        /* Interpret ERRNO= */
84b277
+        e = strv_find_prefix(tags, "ERRNO=");
84b277
+        if (e) {
84b277
+                int status_errno;
84b277
 
84b277
+                if (safe_atoi(e + 6, &status_errno) < 0)
84b277
+                        log_warning_unit(u->id, "Failed to parse ERRNO= field in notification message: %s", e);
84b277
+                else {
84b277
+                        log_debug_unit(u->id, "%s: got %s", u->id, e);
84b277
+
84b277
+                        if (s->status_errno != status_errno) {
84b277
+                                s->status_errno = status_errno;
84b277
+                                notify_dbus = true;
84b277
+                        }
84b277
+                }
84b277
         }
84b277
+
84b277
         if (strv_find(tags, "WATCHDOG=1")) {
84b277
                 log_debug_unit(u->id,
84b277
                                "%s: got WATCHDOG=1", u->id);
84b277
@@ -3530,7 +3554,8 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags) {
84b277
         }
84b277
 
84b277
         /* Notify clients about changed status or main pid */
84b277
-        unit_add_to_dbus_queue(u);
84b277
+        if (notify_dbus)
84b277
+                unit_add_to_dbus_queue(u);
84b277
 }
84b277
 
84b277
 #ifdef HAVE_SYSV_COMPAT
84b277
diff --git a/src/core/service.h b/src/core/service.h
84b277
index ce5b5e0..fa4ef2b 100644
84b277
--- a/src/core/service.h
84b277
+++ b/src/core/service.h
84b277
@@ -187,6 +187,7 @@ struct Service {
84b277
         char *bus_name;
84b277
 
84b277
         char *status_text;
84b277
+        int status_errno;
84b277
 
84b277
         RateLimit start_limit;
84b277
         StartLimitAction start_limit_action;