core/exec-invoke: record correct exit status when failed to locate executable
Follow-up for 4d8b0f0f7a
After the mentioned commit, when the ExecCommand executable is missing,
and failure will be ignored by manager, we exit with EXIT_SUCCESS at executor
side too. The behavior however contradicts systemd.service(5), which states:
> If the executable path is prefixed with "-", an exit code of the command
> normally considered a failure (i.e. non-zero exit status or abnormal exit
> due to signal is _recorded_, but has no further effect and is considered
> equivalent to success.
and thus makes debugging unexpected failures harder. Therefore, let's still
exit with EXIT_EXEC, but just skip LOG_ERR level log.
This commit is contained in:
+10
-19
@@ -4792,26 +4792,17 @@ int exec_invoke(
|
||||
_cleanup_close_ int executable_fd = -EBADF;
|
||||
r = find_executable_full(command->path, /* root= */ NULL, context->exec_search_path, false, &executable, &executable_fd);
|
||||
if (r < 0) {
|
||||
if (r != -ENOMEM && (command->flags & EXEC_COMMAND_IGNORE_FAILURE)) {
|
||||
log_exec_struct_errno(context, params, LOG_INFO, r,
|
||||
"MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
|
||||
LOG_EXEC_INVOCATION_ID(params),
|
||||
LOG_EXEC_MESSAGE(params,
|
||||
"Executable %s missing, skipping: %m",
|
||||
command->path),
|
||||
"EXECUTABLE=%s", command->path);
|
||||
*exit_status = EXIT_SUCCESS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*exit_status = EXIT_EXEC;
|
||||
return log_exec_struct_errno(context, params, LOG_INFO, r,
|
||||
"MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
|
||||
LOG_EXEC_INVOCATION_ID(params),
|
||||
LOG_EXEC_MESSAGE(params,
|
||||
"Failed to locate executable %s: %m",
|
||||
command->path),
|
||||
"EXECUTABLE=%s", command->path);
|
||||
log_exec_struct_errno(context, params, LOG_INFO, r,
|
||||
"MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
|
||||
LOG_EXEC_INVOCATION_ID(params),
|
||||
LOG_EXEC_MESSAGE(params,
|
||||
"Unable to locate executable '%s': %m",
|
||||
command->path),
|
||||
"EXECUTABLE=%s", command->path);
|
||||
/* If the error will be ignored by manager, tune down the log level here. Missing executable
|
||||
* is very much expected in this case. */
|
||||
return r != -ENOMEM && FLAGS_SET(command->flags, EXEC_COMMAND_IGNORE_FAILURE) ? 1 : r;
|
||||
}
|
||||
|
||||
r = add_shifted_fd(keep_fds, ELEMENTSOF(keep_fds), &n_keep_fds, &executable_fd);
|
||||
|
||||
+3
-1
@@ -250,7 +250,9 @@ static int run(int argc, char *argv[]) {
|
||||
status, command.path),
|
||||
"EXECUTABLE=%s", command.path);
|
||||
} else
|
||||
assert(exit_status == EXIT_SUCCESS); /* When 'skip' is chosen in the confirm spawn prompt */
|
||||
/* r == 0: 'skip' is chosen in the confirm spawn prompt
|
||||
* r > 0: expected/ignored failure, do not log at error level */
|
||||
assert((r == 0) == (exit_status == EXIT_SUCCESS));
|
||||
|
||||
return exit_status;
|
||||
}
|
||||
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
# shellcheck source=test/units/util.sh
|
||||
. "$(dirname "$0")"/util.sh
|
||||
|
||||
cat >/run/systemd/system/nonexistent-execstart-exit-status.service <<EOF
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=-/foo/bar/not-exist
|
||||
EOF
|
||||
|
||||
systemctl start nonexistent-execstart-exit-status.service
|
||||
systemctl is-active nonexistent-execstart-exit-status.service
|
||||
assert_eq "$(systemctl show nonexistent-execstart-exit-status.service -P Result)" "success"
|
||||
(( $(systemctl show nonexistent-execstart-exit-status.service -P ExecMainStatus) > 0 ))
|
||||
|
||||
systemctl stop nonexistent-execstart-exit-status.service
|
||||
rm /run/systemd/system/nonexistent-execstart-exit-status.service
|
||||
Reference in New Issue
Block a user