From: Mike Yuan Date: Thu, 9 May 2024 14:05:22 +0000 (+0800) Subject: core/service: store BUSERROR= & VARLINKERROR= received through notification X-Git-Tag: v257-rc1~1083^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9c025022d98787d7ad4e46b57f709434531e55a1;p=thirdparty%2Fsystemd.git core/service: store BUSERROR= & VARLINKERROR= received through notification Closes #6073 --- diff --git a/TODO b/TODO index 534463cd731..92169dea0bf 100644 --- a/TODO +++ b/TODO @@ -478,10 +478,6 @@ Features: - kernel-install - systemd-mount (with PK so that desktop environments could use it to mount disks) -* in the service manager, pick up ERRNO= + BUSERROR= + VARLINKERROR= error - identifiers, and store them along with the exit status of a server and report - via "systemctl status". - * enumerate virtiofs devices during boot-up in a generator, and synthesize mounts for rootfs, /usr/, /home/, /srv/ and some others from it, depending on the "tag". (waits for: https://gitlab.com/virtio-fs/virtiofsd/-/issues/128) diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index b0b45097e30..7ab560a6548 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -2745,6 +2745,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { readonly s FileDescriptorStorePreserve = '...'; readonly s StatusText = '...'; readonly i StatusErrno = ...; + readonly s StatusBusError = '...'; + readonly s StatusVarlinkError = '...'; readonly s Result = '...'; readonly s ReloadResult = '...'; readonly s CleanResult = '...'; @@ -3404,8 +3406,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - - @@ -4026,6 +4026,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { + + + + @@ -4732,11 +4736,11 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { process is currently running while the latter possible contains information collected from the last run even if the process is no longer around. - StatusText contains the status text passed to the service manager via a call - to - sd_notify3. - This may be used by services to inform the service manager about its internal state with a nice - explanatory string. + StatusText, StatusErrno, StatusBusError, + and StatusVarlinkError contain the status text, the error number, + and the D-Bus/Varlink error name passed to the service manager via + sd_notify3, + respectively. They may be used by services to inform the service manager about its internal state. Result encodes the execution result of the last run of the service. It is useful to determine the reason a service failed if it is in the failed state (see @@ -12221,6 +12225,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \ EffectiveMemoryMax, EffectiveTasksMax, and MemoryZSwapWriteback were added in version 256. + StatusBusError + and StatusVarlinkError were added in version 257. Job Objects diff --git a/man/sd_notify.xml b/man/sd_notify.xml index 35c450b1281..f04251bd197 100644 --- a/man/sd_notify.xml +++ b/man/sd_notify.xml @@ -258,12 +258,20 @@ BUSERROR=… If a service fails, the D-Bus error-style error code. Example: - BUSERROR=org.freedesktop.DBus.Error.TimedOut. Note that this assignment is - currently not used by systemd. + BUSERROR=org.freedesktop.DBus.Error.TimedOut. + + VARLINKERROR=… + + If a service fails, the Varlink error-style error code. Example: + VARLINKERROR=org.varlink.service.InvalidParameter. + + + + EXIT_STATUS=… diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index ff970df9574..cf7e2fe0eb8 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -351,6 +351,8 @@ const sd_bus_vtable bus_service_vtable[] = { SD_BUS_PROPERTY("FileDescriptorStorePreserve", "s", bus_property_get_exec_preserve_mode, offsetof(Service, fd_store_preserve_mode), 0), SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("StatusErrno", "i", bus_property_get_int, offsetof(Service, status_errno), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("StatusBusError", "s", NULL, offsetof(Service, status_bus_error), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("StatusVarlinkError", "s", NULL, offsetof(Service, status_varlink_error), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("ReloadResult", "s", property_get_result, offsetof(Service, reload_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("CleanResult", "s", property_get_result, offsetof(Service, clean_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), diff --git a/src/core/service.c b/src/core/service.c index f37a941a6d4..937729cd068 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -468,6 +468,8 @@ static void service_done(Unit *u) { s->pid_file = mfree(s->pid_file); s->status_text = mfree(s->status_text); + s->status_bus_error = mfree(s->status_bus_error); + s->status_varlink_error = mfree(s->status_varlink_error); s->exec_runtime = exec_runtime_free(s->exec_runtime); @@ -1045,6 +1047,14 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) { fprintf(f, "%sStatus Errno: %s\n", prefix, STRERROR(s->status_errno)); + if (s->status_bus_error) + fprintf(f, "%sStatus Bus Error: %s\n", + prefix, s->status_bus_error); + + if (s->status_varlink_error) + fprintf(f, "%sStatus Varlink Error: %s\n", + prefix, s->status_varlink_error); + if (s->n_fd_store_max > 0) fprintf(f, "%sFile Descriptor Store Max: %u\n" @@ -2765,6 +2775,8 @@ static int service_start(Unit *u) { s->status_text = mfree(s->status_text); s->status_errno = 0; + s->status_bus_error = mfree(s->status_bus_error); + s->status_varlink_error = mfree(s->status_varlink_error); s->notify_access_override = _NOTIFY_ACCESS_INVALID; s->notify_state = NOTIFY_UNKNOWN; @@ -3036,6 +3048,8 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) { return r; (void) serialize_item_format(f, "status-errno", "%d", s->status_errno); + (void) serialize_item(f, "status-bus-error", s->status_bus_error); + (void) serialize_item(f, "status-varlink-error", s->status_varlink_error); (void) serialize_dual_timestamp(f, "watchdog-timestamp", &s->watchdog_timestamp); @@ -3370,6 +3384,14 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value, else s->status_errno = i; + } else if (streq(key, "status-bus-error")) { + if (free_and_strdup(&s->status_bus_error, value) < 0) + log_oom_debug(); + + } else if (streq(key, "status-varlink-error")) { + if (free_and_strdup(&s->status_varlink_error, value) < 0) + log_oom_debug(); + } else if (streq(key, "watchdog-timestamp")) (void) deserialize_dual_timestamp(value, &s->watchdog_timestamp); else if (streq(key, "watchdog-original-usec")) @@ -4353,7 +4375,7 @@ static void service_notify_message( if (DEBUG_LOGGING) { _cleanup_free_ char *cc = strv_join(tags, ", "); - log_unit_debug(u, "Got notification message from PID "PID_FMT" (%s)", ucred->pid, empty_to_na(cc)); + log_unit_debug(u, "Got notification message from PID "PID_FMT": %s", ucred->pid, empty_to_na(cc)); } usec_t monotonic_usec = USEC_INFINITY; @@ -4479,7 +4501,7 @@ static void service_notify_message( else { t = strdup(e); if (!t) - log_oom(); + log_oom_warning(); } } @@ -4523,10 +4545,35 @@ static void service_notify_message( } } + static const struct { + const char *tag; + size_t status_offset; + } status_errors[] = { + { "BUSERROR=", offsetof(Service, status_bus_error) }, + { "VARLINKERROR=", offsetof(Service, status_varlink_error) }, + }; + + FOREACH_ELEMENT(i, status_errors) { + e = strv_find_startswith(tags, i->tag); + if (!e) + continue; + + char **status_error = (char**) ((uint8_t*) s + i->status_offset); + + e = empty_to_null(e); + + if (e && !string_is_safe_ascii(e)) { + _cleanup_free_ char *escaped = cescape(e); + log_unit_warning(u, "Got invalid %s string, ignoring: %s", i->tag, strna(escaped)); + } else if (free_and_strdup_warn(status_error, e) > 0) + notify_dbus = true; + } + /* Interpret EXTEND_TIMEOUT= */ e = strv_find_startswith(tags, "EXTEND_TIMEOUT_USEC="); if (e) { usec_t extend_timeout_usec; + if (safe_atou64(e, &extend_timeout_usec) < 0) log_unit_warning(u, "Failed to parse EXTEND_TIMEOUT_USEC=%s", e); else diff --git a/src/core/service.h b/src/core/service.h index 55ea413f40a..1d67d13fda4 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -198,6 +198,8 @@ struct Service { char *bus_name; char *status_text; + char *status_bus_error; + char *status_varlink_error; int status_errno; sd_event_source *timer_event_source;