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