1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-03-11 04:58:19 +03:00

manager: fix error handling after failure to set up child

exec_child() is supposed to set *exit_status when returning failure.
Unfortunately, we didn't do that in two cases. The result would be:
- a bogus error message "Failed at step SUCCESS spawning foo: …",
- a bogus success exit status.

Bugs introduced in 390902012c5177b6b01bc634b2e9c704073d9e7d and
ad21e542b20f0fb292d1958d3a759bf3403522c2.

The code is reworked to add some asserts and not set exit_status in the caller
so that it's clearer (also to the compiler) that it needs to be set.

(cherry picked from commit 5fa01ac0369f0f225ab1e1f90f6b7058cc4deaaf)
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2023-08-10 10:59:55 +02:00
parent 6f28774f39
commit 063d67fe32

View File

@ -4960,6 +4960,7 @@ static int exec_child(
*exit_status = EXIT_SUCCESS;
return 0;
}
*exit_status = EXIT_CONFIRM;
return log_unit_error_errno(unit, SYNTHETIC_ERRNO(ECANCELED),
"Execution cancelled by the user");
@ -5129,14 +5130,18 @@ static int exec_child(
r = set_coredump_filter(context->coredump_filter);
if (ERRNO_IS_PRIVILEGE(r))
log_unit_debug_errno(unit, r, "Failed to adjust coredump_filter, ignoring: %m");
else if (r < 0)
else if (r < 0) {
*exit_status = EXIT_LIMITS;
return log_unit_error_errno(unit, r, "Failed to adjust coredump_filter: %m");
}
}
if (context->nice_set) {
r = setpriority_closest(context->nice);
if (r < 0)
if (r < 0) {
*exit_status = EXIT_NICE;
return log_unit_error_errno(unit, r, "Failed to set up process scheduling priority (nice level): %m");
}
}
if (context->cpu_sched_set) {
@ -5583,11 +5588,11 @@ static int exec_child(
LOG_UNIT_MESSAGE(unit, "Executable %s missing, skipping: %m",
command->path),
"EXECUTABLE=%s", command->path);
*exit_status = EXIT_SUCCESS;
return 0;
}
*exit_status = EXIT_EXEC;
return log_unit_struct_errno(unit, LOG_INFO, r,
"MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
LOG_UNIT_INVOCATION_ID(unit),
@ -6049,7 +6054,7 @@ int exec_spawn(Unit *unit,
return log_unit_error_errno(unit, errno, "Failed to fork: %m");
if (pid == 0) {
int exit_status = EXIT_SUCCESS;
int exit_status;
r = exec_child(unit,
command,
@ -6067,9 +6072,8 @@ int exec_spawn(Unit *unit,
&exit_status);
if (r < 0) {
const char *status =
exit_status_to_string(exit_status,
EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD);
const char *status = ASSERT_PTR(
exit_status_to_string(exit_status, EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD));
log_unit_struct_errno(unit, LOG_ERR, r,
"MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
@ -6077,7 +6081,8 @@ int exec_spawn(Unit *unit,
LOG_UNIT_MESSAGE(unit, "Failed at step %s spawning %s: %m",
status, command->path),
"EXECUTABLE=%s", command->path);
}
} else
assert(exit_status == EXIT_SUCCESS);
_exit(exit_status);
}