mirror of
https://github.com/systemd/systemd
synced 2024-10-15 20:45:09 +00:00
Merge pull request #31351 from YHNdnzj/exit-status-no-executable
core/exec-invoke: record correct exit status when failed to locate executable
This commit is contained in:
commit
f927b872d6
|
@ -4792,26 +4792,16 @@ 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_NOTICE, r,
|
||||
"MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
|
||||
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);
|
||||
|
|
|
@ -616,23 +616,26 @@ bool exec_needs_ipc_namespace(const ExecContext *context);
|
|||
#define LOG_EXEC_INVOCATION_ID_FIELD_FORMAT(ep) \
|
||||
((ep)->runtime_scope == RUNTIME_SCOPE_USER ? "USER_INVOCATION_ID=%s" : "INVOCATION_ID=%s")
|
||||
|
||||
#define log_exec_full_errno_zerook(ec, ep, level, error, ...) \
|
||||
({ \
|
||||
const ExecContext *_c = (ec); \
|
||||
const ExecParameters *_p = (ep); \
|
||||
const int _l = (level); \
|
||||
bool _do_log = !(log_get_max_level() < LOG_PRI(_l) || \
|
||||
!(_c->log_level_max < 0 || \
|
||||
_c->log_level_max >= LOG_PRI(_l))); \
|
||||
LOG_CONTEXT_PUSH_IOV(_c->log_extra_fields, \
|
||||
_c->n_log_extra_fields); \
|
||||
!_do_log ? -ERRNO_VALUE(error) : \
|
||||
log_object_internal(_l, error, PROJECT_FILE, \
|
||||
__LINE__, __func__, \
|
||||
LOG_EXEC_ID_FIELD(_p), \
|
||||
_p->unit_id, \
|
||||
LOG_EXEC_INVOCATION_ID_FIELD(_p), \
|
||||
_p->invocation_id_string, ##__VA_ARGS__); \
|
||||
/* Like LOG_MESSAGE(), but with the unit name prefixed. */
|
||||
#define LOG_EXEC_MESSAGE(ep, fmt, ...) LOG_MESSAGE("%s: " fmt, (ep)->unit_id, ##__VA_ARGS__)
|
||||
#define LOG_EXEC_ID(ep) LOG_EXEC_ID_FIELD_FORMAT(ep), (ep)->unit_id
|
||||
#define LOG_EXEC_INVOCATION_ID(ep) LOG_EXEC_INVOCATION_ID_FIELD_FORMAT(ep), (ep)->invocation_id_string
|
||||
|
||||
#define log_exec_full_errno_zerook(ec, ep, level, error, ...) \
|
||||
({ \
|
||||
const ExecContext *_c = (ec); \
|
||||
const ExecParameters *_p = (ep); \
|
||||
const int _l = (level); \
|
||||
bool _do_log = _c->log_level_max >= 0 && \
|
||||
_c->log_level_max < LOG_PRI(_l); \
|
||||
LOG_CONTEXT_PUSH_IOV(_c->log_extra_fields, \
|
||||
_c->n_log_extra_fields); \
|
||||
!_do_log ? -ERRNO_VALUE(error) : \
|
||||
log_object_internal(_l, error, \
|
||||
PROJECT_FILE, __LINE__, __func__, \
|
||||
LOG_EXEC_ID(_p), \
|
||||
LOG_EXEC_INVOCATION_ID(_p), \
|
||||
##__VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define log_exec_full_errno(ec, ep, level, error, ...) \
|
||||
|
@ -656,48 +659,29 @@ bool exec_needs_ipc_namespace(const ExecContext *context);
|
|||
#define log_exec_warning_errno(ec, ep, error, ...) log_exec_full_errno(ec, ep, LOG_WARNING, error, __VA_ARGS__)
|
||||
#define log_exec_error_errno(ec, ep, error, ...) log_exec_full_errno(ec, ep, LOG_ERR, error, __VA_ARGS__)
|
||||
|
||||
#define log_exec_struct_errno(ec, ep, level, error, ...) \
|
||||
({ \
|
||||
const ExecContext *_c = (ec); \
|
||||
const ExecParameters *_p = (ep); \
|
||||
const int _l = (level); \
|
||||
bool _do_log = !(_c->log_level_max < 0 || \
|
||||
_c->log_level_max >= LOG_PRI(_l)); \
|
||||
LOG_CONTEXT_PUSH_IOV(_c->log_extra_fields, \
|
||||
_c->n_log_extra_fields); \
|
||||
_do_log ? \
|
||||
log_struct_errno(_l, error, __VA_ARGS__, LOG_EXEC_ID_FIELD_FORMAT(_p), _p->unit_id) : \
|
||||
-ERRNO_VALUE(error); \
|
||||
#define log_exec_struct_errno(ec, ep, level, error, ...) \
|
||||
({ \
|
||||
const ExecContext *_c = (ec); \
|
||||
const ExecParameters *_p = (ep); \
|
||||
const int _l = (level); \
|
||||
bool _do_log = _c->log_level_max >= 0 && \
|
||||
_c->log_level_max < LOG_PRI(_l); \
|
||||
LOG_CONTEXT_PUSH_IOV(_c->log_extra_fields, \
|
||||
_c->n_log_extra_fields); \
|
||||
!_do_log ? -ERRNO_VALUE(error) : \
|
||||
log_struct_errno(_l, error, \
|
||||
LOG_EXEC_ID(_p), \
|
||||
LOG_EXEC_INVOCATION_ID(_p), \
|
||||
__VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define log_exec_struct(ec, ep, level, ...) log_exec_struct_errno(ec, ep, level, 0, __VA_ARGS__)
|
||||
|
||||
#define log_exec_struct_iovec_errno(ec, ep, level, error, iovec, n_iovec) \
|
||||
({ \
|
||||
const ExecContext *_c = (ec); \
|
||||
const ExecParameters *_p = (ep); \
|
||||
const int _l = (level); \
|
||||
bool _do_log = !(_c->log_level_max < 0 || \
|
||||
_c->log_level_max >= LOG_PRI(_l)); \
|
||||
LOG_CONTEXT_PUSH_IOV(_c->log_extra_fields, \
|
||||
_c->n_log_extra_fields); \
|
||||
_do_log ? \
|
||||
log_struct_iovec_errno(_l, error, iovec, n_iovec) : \
|
||||
-ERRNO_VALUE(error); \
|
||||
})
|
||||
|
||||
#define log_exec_struct_iovec(ec, ep, level, iovec, n_iovec) log_exec_struct_iovec_errno(ec, ep, level, 0, iovec, n_iovec)
|
||||
|
||||
/* Like LOG_MESSAGE(), but with the unit name prefixed. */
|
||||
#define LOG_EXEC_MESSAGE(ep, fmt, ...) LOG_MESSAGE("%s: " fmt, (ep)->unit_id, ##__VA_ARGS__)
|
||||
#define LOG_EXEC_ID(ep) LOG_EXEC_ID_FIELD_FORMAT(ep), (ep)->unit_id
|
||||
#define LOG_EXEC_INVOCATION_ID(ep) LOG_EXEC_INVOCATION_ID_FIELD_FORMAT(ep), (ep)->invocation_id_string
|
||||
|
||||
#define _LOG_CONTEXT_PUSH_EXEC(ec, ep, p, c) \
|
||||
const ExecContext *c = (ec); \
|
||||
const ExecParameters *p = (ep); \
|
||||
#define _LOG_CONTEXT_PUSH_EXEC(ec, ep, p, c) \
|
||||
const ExecContext *c = (ec); \
|
||||
const ExecParameters *p = (ep); \
|
||||
LOG_CONTEXT_PUSH_KEY_VALUE(LOG_EXEC_ID_FIELD(p), p->unit_id); \
|
||||
LOG_CONTEXT_PUSH_KEY_VALUE(LOG_EXEC_INVOCATION_ID_FIELD(p), p->invocation_id_string); \
|
||||
LOG_CONTEXT_PUSH_KEY_VALUE(LOG_EXEC_INVOCATION_ID_FIELD(p), p->invocation_id_string); \
|
||||
LOG_CONTEXT_PUSH_IOV(c->log_extra_fields, c->n_log_extra_fields)
|
||||
|
||||
#define LOG_CONTEXT_PUSH_EXEC(ec, ep) \
|
||||
|
|
|
@ -245,12 +245,13 @@ static int run(int argc, char *argv[]) {
|
|||
|
||||
log_exec_struct_errno(&context, ¶ms, LOG_ERR, r,
|
||||
"MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
|
||||
LOG_EXEC_INVOCATION_ID(¶ms),
|
||||
LOG_EXEC_MESSAGE(¶ms, "Failed at step %s spawning %s: %m",
|
||||
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;
|
||||
}
|
||||
|
|
22
test/units/testsuite-07.pr-31351.sh
Executable file
22
test/units/testsuite-07.pr-31351.sh
Executable file
|
@ -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
|
Loading…
Reference in a new issue