#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "serialize.h"
#include "service.h"
#include "signal-util.h"
#include "special.h"
s->exec_context.keyring_mode = MANAGER_IS_SYSTEM(u->manager) ?
EXEC_KEYRING_PRIVATE : EXEC_KEYRING_INHERIT;
+
+ s->watchdog_original_usec = USEC_INFINITY;
}
static void service_unwatch_control_pid(Service *s) {
if (s->watchdog_override_enable)
return s->watchdog_override_usec;
- else
- return s->watchdog_usec;
+
+ return s->watchdog_original_usec;
}
static void service_start_watchdog(Service *s) {
- int r;
usec_t watchdog_usec;
+ int r;
assert(s);
watchdog_usec = service_get_watchdog_usec(s);
- if (IN_SET(watchdog_usec, 0, USEC_INFINITY))
+ if (IN_SET(watchdog_usec, 0, USEC_INFINITY)) {
+ service_stop_watchdog(s);
return;
+ }
if (s->watchdog_event_source) {
r = sd_event_source_set_time(s->watchdog_event_source, usec_add(s->watchdog_timestamp.monotonic, watchdog_usec));
* of living before we consider a service died. */
r = sd_event_source_set_priority(s->watchdog_event_source, SD_EVENT_PRIORITY_IDLE);
}
-
if (r < 0)
log_unit_warning_errno(UNIT(s), r, "Failed to install watchdog timer: %m");
}
-static void service_extend_timeout(Service *s, usec_t extend_timeout_usec) {
- assert(s);
+static void service_extend_event_source_timeout(Service *s, sd_event_source *source, usec_t extended) {
+ usec_t current;
+ int r;
- if (s->timer_event_source) {
- uint64_t current = 0, extended = 0;
- int r;
+ assert(s);
- if (IN_SET(extend_timeout_usec, 0, USEC_INFINITY))
- return;
+ /* Extends the specified event source timer to at least the specified time, unless it is already later
+ * anyway. */
- extended = usec_add(now(CLOCK_MONOTONIC), extend_timeout_usec);
+ if (!source)
+ return;
- r = sd_event_source_get_time(s->timer_event_source, ¤t);
- if (r < 0)
- log_unit_error_errno(UNIT(s), r, "Failed to retrieve timeout timer: %m");
- else if (extended > current) {
- r = sd_event_source_set_time(s->timer_event_source, extended);
- if (r < 0)
- log_unit_warning_errno(UNIT(s), r, "Failed to set timeout timer: %m");
- }
+ r = sd_event_source_get_time(source, ¤t);
+ if (r < 0) {
+ const char *desc;
+ (void) sd_event_source_get_description(s->timer_event_source, &desc);
+ log_unit_warning_errno(UNIT(s), r, "Failed to retrieve timeout time for event source '%s', ignoring: %m", strna(desc));
+ return;
+ }
- if (s->watchdog_event_source) {
- /* extend watchdog if necessary. We've asked for an extended timeout so we
- * shouldn't expect a watchdog timeout in the interval in between */
- r = sd_event_source_get_time(s->watchdog_event_source, ¤t);
- if (r < 0) {
- log_unit_error_errno(UNIT(s), r, "Failed to retrieve watchdog timer: %m");
- return;
- }
+ if (current >= extended) /* Current timeout is already longer, ignore this. */
+ return;
- if (extended > current) {
- r = sd_event_source_set_time(s->watchdog_event_source, extended);
- if (r < 0)
- log_unit_warning_errno(UNIT(s), r, "Failed to set watchdog timer: %m");
- }
- }
+ r = sd_event_source_set_time(source, extended);
+ if (r < 0) {
+ const char *desc;
+ (void) sd_event_source_get_description(s->timer_event_source, &desc);
+ log_unit_warning_errno(UNIT(s), r, "Failed to set timeout time for even source '%s', ignoring %m", strna(desc));
}
}
+static void service_extend_timeout(Service *s, usec_t extend_timeout_usec) {
+ usec_t extended;
+
+ assert(s);
+
+ if (IN_SET(extend_timeout_usec, 0, USEC_INFINITY))
+ return;
+
+ extended = usec_add(now(CLOCK_MONOTONIC), extend_timeout_usec);
+
+ service_extend_event_source_timeout(s, s->timer_event_source, extended);
+ service_extend_event_source_timeout(s, s->watchdog_event_source, extended);
+}
+
static void service_reset_watchdog(Service *s) {
assert(s);
service_start_watchdog(s);
}
-static void service_reset_watchdog_timeout(Service *s, usec_t watchdog_override_usec) {
+static void service_override_watchdog_timeout(Service *s, usec_t watchdog_override_usec) {
assert(s);
s->watchdog_override_enable = true;
if (UNIT(s)->load_state != UNIT_LOADED)
return 0;
- if (!s->exec_command[SERVICE_EXEC_START] && !s->exec_command[SERVICE_EXEC_STOP]) {
- log_unit_error(UNIT(s), "Service lacks both ExecStart= and ExecStop= setting. Refusing.");
+ if (!s->exec_command[SERVICE_EXEC_START] && !s->exec_command[SERVICE_EXEC_STOP]
+ && UNIT(s)->success_action == EMERGENCY_ACTION_NONE) {
+ /* FailureAction= only makes sense if one of the start or stop commands is specified.
+ * SuccessAction= will be executed unconditionally if no commands are specified. Hence,
+ * either a command or SuccessAction= are required. */
+
+ log_unit_error(UNIT(s), "Service has no ExecStart=, ExecStop=, or SuccessAction=. Refusing.");
return -ENOEXEC;
}
return -ENOEXEC;
}
- if (!s->remain_after_exit && !s->exec_command[SERVICE_EXEC_START]) {
- log_unit_error(UNIT(s), "Service has no ExecStart= setting, which is only allowed for RemainAfterExit=yes services. Refusing.");
+ if (!s->remain_after_exit && !s->exec_command[SERVICE_EXEC_START] && UNIT(s)->success_action == EMERGENCY_ACTION_NONE) {
+ log_unit_error(UNIT(s), "Service has no ExecStart= and no SuccessAction= settings and does not have RemainAfterExit=yes set. Refusing.");
return -ENOEXEC;
}
* require it, so that we fail if we can't acquire
* it. */
- r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
+ r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
if (r < 0)
return r;
} else {
/* In the --user instance there's no sysinit.target,
* in that case require basic.target instead. */
- r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_BASIC_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_BASIC_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
if (r < 0)
return r;
}
/* Second, if the rest of the base system is in the same
* transaction, order us after it, but do not pull it in or
* even require it. */
- r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_BASIC_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_BASIC_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
if (r < 0)
return r;
/* Third, add us in for normal shutdown. */
- return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
+ return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
}
static void service_fix_output(Service *s) {
if (!s->bus_name)
return 0;
- r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_DBUS_SOCKET, NULL, true, UNIT_DEPENDENCY_FILE);
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_DBUS_SOCKET, true, UNIT_DEPENDENCY_FILE);
if (r < 0)
return log_unit_error_errno(UNIT(s), r, "Failed to add dependency on " SPECIAL_DBUS_SOCKET ": %m");
/* We always want to be ordered against dbus.socket if both are in the transaction. */
- r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_DBUS_SOCKET, NULL, true, UNIT_DEPENDENCY_FILE);
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_DBUS_SOCKET, true, UNIT_DEPENDENCY_FILE);
if (r < 0)
return log_unit_error_errno(UNIT(s), r, "Failed to add dependency on " SPECIAL_DBUS_SOCKET ": %m");
return -ENOMEM;
rfds[0] = s->socket_fd;
- rfd_names = strv_new("connection", NULL);
+ rfd_names = strv_new("connection");
if (!rfd_names)
return -ENOMEM;
ExecFlags flags,
pid_t *_pid) {
- ExecParameters exec_params = {
+ _cleanup_(exec_params_clear) ExecParameters exec_params = {
.flags = flags,
.stdin_fd = -1,
.stdout_fd = -1,
}
}
- unit_set_exec_params(UNIT(s), &exec_params);
+ r = unit_set_exec_params(UNIT(s), &exec_params);
+ if (r < 0)
+ return r;
final_env = strv_env_merge(2, exec_params.environment, our_env, NULL);
if (!final_env)
SET_FLAG(exec_params.flags, EXEC_NSS_BYPASS_BUS,
MANAGER_IS_SYSTEM(UNIT(s)->manager) && unit_has_name(UNIT(s), SPECIAL_DBUS_SERVICE));
- exec_params.environment = final_env;
+ strv_free_and_replace(exec_params.environment, final_env);
exec_params.fds = fds;
exec_params.fd_names = fd_names;
exec_params.n_socket_fds = n_socket_fds;
exec_params.n_storage_fds = n_storage_fds;
- exec_params.watchdog_usec = s->watchdog_usec;
+ exec_params.watchdog_usec = service_get_watchdog_usec(s);
exec_params.selinux_context_net = s->socket_fd_selinux_context_net;
if (s->type == SERVICE_IDLE)
exec_params.idle_pipe = UNIT(s)->manager->idle_pipe;
if (s->result == SERVICE_SUCCESS)
s->result = f;
- if (s->result != SERVICE_SUCCESS)
- log_unit_warning(UNIT(s), "Failed with result '%s'.", service_result_to_string(s->result));
+ unit_log_result(UNIT(s), s->result == SERVICE_SUCCESS, service_result_to_string(s->result));
if (allow_restart && service_shall_restart(s))
s->will_auto_restart = true;
goto fail;
}
+ /* We force a fake state transition here. Otherwise, the unit would go directly from
+ * SERVICE_DEAD to SERVICE_DEAD without SERVICE_ACTIVATING or SERVICE_ACTIVE
+ * inbetween. This way we can later trigger actions that depend on the state
+ * transition, including SuccessAction=. */
+ service_set_state(s, SERVICE_START);
+
service_enter_start_post(s);
return;
}
s->notify_state = NOTIFY_UNKNOWN;
+ s->watchdog_original_usec = s->watchdog_usec;
s->watchdog_override_enable = false;
- s->watchdog_override_usec = 0;
+ s->watchdog_override_usec = USEC_INFINITY;
exec_command_reset_status_list_array(s->exec_command, _SERVICE_EXEC_COMMAND_MAX);
exec_status_reset(&s->main_exec_status);
}
static int service_serialize_exec_command(Unit *u, FILE *f, ExecCommand *command) {
+ _cleanup_free_ char *args = NULL, *p = NULL;
+ size_t allocated = 0, length = 0;
Service *s = SERVICE(u);
+ const char *type, *key;
ServiceExecCommand id;
unsigned idx;
- const char *type;
char **arg;
- _cleanup_free_ char *args = NULL, *p = NULL;
- size_t allocated = 0, length = 0;
assert(s);
assert(f);
idx = service_exec_command_index(u, id, command);
STRV_FOREACH(arg, command->argv) {
- size_t n;
_cleanup_free_ char *e = NULL;
+ size_t n;
- e = xescape(*arg, WHITESPACE);
+ e = cescape(*arg);
if (!e)
- return -ENOMEM;
+ return log_oom();
n = strlen(e);
if (!GREEDY_REALLOC(args, allocated, length + 1 + n + 1))
- return -ENOMEM;
+ return log_oom();
if (length > 0)
args[length++] = ' ';
}
if (!GREEDY_REALLOC(args, allocated, length + 1))
- return -ENOMEM;
+ return log_oom();
+
args[length++] = 0;
- p = xescape(command->path, WHITESPACE);
+ p = cescape(command->path);
if (!p)
return -ENOMEM;
- fprintf(f, "%s-command=%s %u %s %s\n", type, service_exec_command_to_string(id), idx, p, args);
-
- return 0;
+ key = strjoina(type, "-command");
+ return serialize_item_format(f, key, "%s %u %s %s", service_exec_command_to_string(id), idx, p, args);
}
static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
assert(f);
assert(fds);
- unit_serialize_item(u, f, "state", service_state_to_string(s->state));
- unit_serialize_item(u, f, "result", service_result_to_string(s->result));
- unit_serialize_item(u, f, "reload-result", service_result_to_string(s->reload_result));
+ (void) serialize_item(f, "state", service_state_to_string(s->state));
+ (void) serialize_item(f, "result", service_result_to_string(s->result));
+ (void) serialize_item(f, "reload-result", service_result_to_string(s->reload_result));
if (s->control_pid > 0)
- unit_serialize_item_format(u, f, "control-pid", PID_FMT, s->control_pid);
+ (void) serialize_item_format(f, "control-pid", PID_FMT, s->control_pid);
if (s->main_pid_known && s->main_pid > 0)
- unit_serialize_item_format(u, f, "main-pid", PID_FMT, s->main_pid);
+ (void) serialize_item_format(f, "main-pid", PID_FMT, s->main_pid);
- unit_serialize_item(u, f, "main-pid-known", yes_no(s->main_pid_known));
- unit_serialize_item(u, f, "bus-name-good", yes_no(s->bus_name_good));
- unit_serialize_item(u, f, "bus-name-owner", s->bus_name_owner);
+ (void) serialize_bool(f, "main-pid-known", s->main_pid_known);
+ (void) serialize_bool(f, "bus-name-good", s->bus_name_good);
+ (void) serialize_bool(f, "bus-name-owner", s->bus_name_owner);
- unit_serialize_item_format(u, f, "n-restarts", "%u", s->n_restarts);
- unit_serialize_item(u, f, "flush-n-restarts", yes_no(s->flush_n_restarts));
+ (void) serialize_item_format(f, "n-restarts", "%u", s->n_restarts);
+ (void) serialize_bool(f, "flush-n-restarts", s->flush_n_restarts);
- r = unit_serialize_item_escaped(u, f, "status-text", s->status_text);
+ r = serialize_item_escaped(f, "status-text", s->status_text);
if (r < 0)
return r;
service_serialize_exec_command(u, f, s->control_command);
service_serialize_exec_command(u, f, s->main_command);
- r = unit_serialize_item_fd(u, f, fds, "stdin-fd", s->stdin_fd);
+ r = serialize_fd(f, fds, "stdin-fd", s->stdin_fd);
if (r < 0)
return r;
- r = unit_serialize_item_fd(u, f, fds, "stdout-fd", s->stdout_fd);
+ r = serialize_fd(f, fds, "stdout-fd", s->stdout_fd);
if (r < 0)
return r;
- r = unit_serialize_item_fd(u, f, fds, "stderr-fd", s->stderr_fd);
+ r = serialize_fd(f, fds, "stderr-fd", s->stderr_fd);
if (r < 0)
return r;
if (s->exec_fd_event_source) {
- r = unit_serialize_item_fd(u, f, fds, "exec-fd", sd_event_source_get_io_fd(s->exec_fd_event_source));
+ r = serialize_fd(f, fds, "exec-fd", sd_event_source_get_io_fd(s->exec_fd_event_source));
if (r < 0)
return r;
- unit_serialize_item(u, f, "exec-fd-hot", yes_no(s->exec_fd_hot));
+
+ (void) serialize_bool(f, "exec-fd-hot", s->exec_fd_hot);
}
if (UNIT_ISSET(s->accept_socket)) {
- r = unit_serialize_item(u, f, "accept-socket", UNIT_DEREF(s->accept_socket)->id);
+ r = serialize_item(f, "accept-socket", UNIT_DEREF(s->accept_socket)->id);
if (r < 0)
return r;
}
- r = unit_serialize_item_fd(u, f, fds, "socket-fd", s->socket_fd);
+ r = serialize_fd(f, fds, "socket-fd", s->socket_fd);
if (r < 0)
return r;
copy = fdset_put_dup(fds, fs->fd);
if (copy < 0)
- return copy;
+ return log_error_errno(copy, "Failed to copy file descriptor for serialization: %m");
c = cescape(fs->fdname);
+ if (!c)
+ return log_oom();
- unit_serialize_item_format(u, f, "fd-store-fd", "%i %s", copy, strempty(c));
+ (void) serialize_item_format(f, "fd-store-fd", "%i %s", copy, c);
}
if (s->main_exec_status.pid > 0) {
- unit_serialize_item_format(u, f, "main-exec-status-pid", PID_FMT, s->main_exec_status.pid);
- dual_timestamp_serialize(f, "main-exec-status-start", &s->main_exec_status.start_timestamp);
- dual_timestamp_serialize(f, "main-exec-status-exit", &s->main_exec_status.exit_timestamp);
+ (void) serialize_item_format(f, "main-exec-status-pid", PID_FMT, s->main_exec_status.pid);
+ (void) serialize_dual_timestamp(f, "main-exec-status-start", &s->main_exec_status.start_timestamp);
+ (void) serialize_dual_timestamp(f, "main-exec-status-exit", &s->main_exec_status.exit_timestamp);
if (dual_timestamp_is_set(&s->main_exec_status.exit_timestamp)) {
- unit_serialize_item_format(u, f, "main-exec-status-code", "%i", s->main_exec_status.code);
- unit_serialize_item_format(u, f, "main-exec-status-status", "%i", s->main_exec_status.status);
+ (void) serialize_item_format(f, "main-exec-status-code", "%i", s->main_exec_status.code);
+ (void) serialize_item_format(f, "main-exec-status-status", "%i", s->main_exec_status.status);
}
}
- dual_timestamp_serialize(f, "watchdog-timestamp", &s->watchdog_timestamp);
-
- unit_serialize_item(u, f, "forbid-restart", yes_no(s->forbid_restart));
+ (void) serialize_dual_timestamp(f, "watchdog-timestamp", &s->watchdog_timestamp);
+ (void) serialize_bool(f, "forbid-restart", s->forbid_restart);
if (s->watchdog_override_enable)
- unit_serialize_item_format(u, f, "watchdog-override-usec", USEC_FMT, s->watchdog_override_usec);
+ (void) serialize_item_format(f, "watchdog-override-usec", USEC_FMT, s->watchdog_override_usec);
+
+ if (s->watchdog_original_usec != USEC_INFINITY)
+ (void) serialize_item_format(f, "watchdog-original-usec", USEC_FMT, s->watchdog_original_usec);
return 0;
}
_cleanup_free_ char *arg = NULL;
r = extract_first_word(&value, &arg, NULL, EXTRACT_CUNESCAPE);
+ if (r < 0)
+ return r;
if (r == 0)
break;
- else if (r < 0)
- return r;
switch (state) {
case STATE_EXEC_COMMAND_TYPE:
r = cunescape(value, 0, &t);
if (r < 0)
- log_unit_debug_errno(u, r, "Failed to unescape status text: %s", value);
- else {
- free(s->status_text);
- s->status_text = t;
- }
+ log_unit_debug_errno(u, r, "Failed to unescape status text '%s': %m", value);
+ else
+ free_and_replace(s->status_text, t);
} else if (streq(key, "accept-socket")) {
Unit *socket;
r = manager_load_unit(u->manager, value, NULL, NULL, &socket);
if (r < 0)
- log_unit_debug_errno(u, r, "Failed to load accept-socket unit: %s", value);
+ log_unit_debug_errno(u, r, "Failed to load accept-socket unit '%s': %m", value);
else {
unit_ref_set(&s->accept_socket, u, socket);
SOCKET(socket)->n_connections++;
else
s->main_exec_status.status = i;
} else if (streq(key, "main-exec-status-start"))
- dual_timestamp_deserialize(value, &s->main_exec_status.start_timestamp);
+ deserialize_dual_timestamp(value, &s->main_exec_status.start_timestamp);
else if (streq(key, "main-exec-status-exit"))
- dual_timestamp_deserialize(value, &s->main_exec_status.exit_timestamp);
+ deserialize_dual_timestamp(value, &s->main_exec_status.exit_timestamp);
else if (streq(key, "watchdog-timestamp"))
- dual_timestamp_deserialize(value, &s->watchdog_timestamp);
+ deserialize_dual_timestamp(value, &s->watchdog_timestamp);
else if (streq(key, "forbid-restart")) {
int b;
safe_close(fd);
}
} else if (streq(key, "watchdog-override-usec")) {
- usec_t watchdog_override_usec;
- if (timestamp_deserialize(value, &watchdog_override_usec) < 0)
+ if (deserialize_usec(value, &s->watchdog_override_usec) < 0)
log_unit_debug(u, "Failed to parse watchdog_override_usec value: %s", value);
- else {
+ else
s->watchdog_override_enable = true;
- s->watchdog_override_usec = watchdog_override_usec;
- }
+
+ } else if (streq(key, "watchdog-original-usec")) {
+ if (deserialize_usec(value, &s->watchdog_original_usec) < 0)
+ log_unit_debug(u, "Failed to parse watchdog_original_usec value: %s", value);
+
} else if (STR_IN_SET(key, "main-command", "control-command")) {
r = service_deserialize_exec_command(u, key, value);
if (r < 0)
/* When this is a successful exit, let's log about the exit code on DEBUG level. If this is a failure
* and the process exited on its own via exit(), then let's make this a NOTICE, under the assumption
- * that the service already logged the reason at a higher log level on its own. However, if the service
- * died due to a signal, then it most likely didn't say anything about any reason, hence let's raise
- * our log level to WARNING then. */
-
- log_struct(f == SERVICE_SUCCESS ? LOG_DEBUG :
- (code == CLD_EXITED ? LOG_NOTICE : LOG_WARNING),
- LOG_UNIT_MESSAGE(u, "Main process exited, code=%s, status=%i/%s",
- sigchld_code_to_string(code), status,
- strna(code == CLD_EXITED
- ? exit_status_to_string(status, EXIT_STATUS_FULL)
- : signal_to_string(status))),
- "EXIT_CODE=%s", sigchld_code_to_string(code),
- "EXIT_STATUS=%i", status,
- LOG_UNIT_ID(u),
- LOG_UNIT_INVOCATION_ID(u));
+ * that the service already logged the reason at a higher log level on its own. (Internally,
+ * unit_log_process_exit() will possibly bump this to WARNING if the service died due to a signal.) */
+ unit_log_process_exit(
+ u, f == SERVICE_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
+ "Main process",
+ service_exec_command_to_string(SERVICE_EXEC_START),
+ code, status);
if (s->result == SERVICE_SUCCESS)
s->result = f;
f = SERVICE_SUCCESS;
}
- log_unit_full(u, f == SERVICE_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0,
- "Control process exited, code=%s status=%i",
- sigchld_code_to_string(code), status);
+ unit_log_process_exit(
+ u, f == SERVICE_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
+ "Control process",
+ service_exec_command_to_string(s->control_command_id),
+ code, status);
if (s->result == SERVICE_SUCCESS)
s->result = f;
}
if (r > 0) {
service_set_main_pid(s, new_main_pid);
- unit_watch_pid(UNIT(s), new_main_pid);
+
+ r = unit_watch_pid(UNIT(s), new_main_pid);
+ if (r < 0)
+ log_unit_warning_errno(UNIT(s), r, "Failed to watch new main PID "PID_FMT" for service: %m", new_main_pid);
+
notify_dbus = true;
}
}
_cleanup_free_ char *t = NULL;
if (!isempty(e)) {
- if (!utf8_is_valid(e))
- log_unit_warning(u, "Status message in notification message is not UTF-8 clean.");
+ /* Note that this size limit check is mostly paranoia: since the datagram size we are willing
+ * to process is already limited to NOTIFY_BUFFER_MAX, this limit here should never be hit. */
+ if (strlen(e) > STATUS_TEXT_MAX)
+ log_unit_warning(u, "Status message overly long (%zu > %u), ignoring.", strlen(e), STATUS_TEXT_MAX);
+ else if (!utf8_is_valid(e))
+ log_unit_warning(u, "Status message in notification message is not UTF-8 clean, ignoring.");
else {
t = strdup(e);
if (!t)
status_errno = parse_errno(e);
if (status_errno < 0)
log_unit_warning_errno(u, status_errno,
- "Failed to parse ERRNO= field in notification message: %s", e);
+ "Failed to parse ERRNO= field value '%s' in notification message: %m", e);
else if (s->status_errno != status_errno) {
s->status_errno = status_errno;
notify_dbus = true;
if (safe_atou64(e, &watchdog_override_usec) < 0)
log_unit_warning(u, "Failed to parse WATCHDOG_USEC=%s", e);
else
- service_reset_watchdog_timeout(s, watchdog_override_usec);
+ service_override_watchdog_timeout(s, watchdog_override_usec);
}
/* Process FD store messages. Either FDSTOREREMOVE=1 for removal, or FDSTORE=1 for addition. In both cases,