mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-08 21:17:47 +03:00
core: when determining whether a process exit status is clean, consider whether it is a command or a daemon
SIGTERM should be considered a clean exit code for daemons (i.e. long-running processes, as a daemon without SIGTERM handler may be shut down without issues via SIGTERM still) while it should not be considered a clean exit code for commands (i.e. short-running processes). Let's add two different clean checking modes for this, and use the right one at the appropriate places. Fixes: #4275
This commit is contained in:
parent
38107f5a4a
commit
1f0958f640
@ -177,17 +177,17 @@ const char* exit_status_to_string(int status, ExitStatusLevel level) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool is_clean_exit(int code, int status, ExitStatusSet *success_status) {
|
||||
bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success_status) {
|
||||
|
||||
if (code == CLD_EXITED)
|
||||
return status == 0 ||
|
||||
(success_status &&
|
||||
set_contains(success_status->status, INT_TO_PTR(status)));
|
||||
|
||||
/* If a daemon does not implement handlers for some of the
|
||||
* signals that's not considered an unclean shutdown */
|
||||
/* If a daemon does not implement handlers for some of the signals that's not considered an unclean shutdown */
|
||||
if (code == CLD_KILLED)
|
||||
return IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE) ||
|
||||
return
|
||||
(clean == EXIT_CLEAN_DAEMON && IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE)) ||
|
||||
(success_status &&
|
||||
set_contains(success_status->signal, INT_TO_PTR(status)));
|
||||
|
||||
|
@ -98,7 +98,12 @@ typedef struct ExitStatusSet {
|
||||
|
||||
const char* exit_status_to_string(int status, ExitStatusLevel level) _const_;
|
||||
|
||||
bool is_clean_exit(int code, int status, ExitStatusSet *success_status);
|
||||
typedef enum ExitClean {
|
||||
EXIT_CLEAN_DAEMON,
|
||||
EXIT_CLEAN_COMMAND,
|
||||
} ExitClean;
|
||||
|
||||
bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success_status);
|
||||
|
||||
void exit_status_set_free(ExitStatusSet *x);
|
||||
bool exit_status_set_is_empty(ExitStatusSet *x);
|
||||
|
@ -868,7 +868,7 @@ static void busname_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
|
||||
n->control_pid = 0;
|
||||
|
||||
if (is_clean_exit(code, status, NULL))
|
||||
if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
|
||||
f = BUSNAME_SUCCESS;
|
||||
else if (code == CLD_EXITED)
|
||||
f = BUSNAME_FAILURE_EXIT_CODE;
|
||||
|
@ -1159,7 +1159,7 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
|
||||
m->control_pid = 0;
|
||||
|
||||
if (is_clean_exit(code, status, NULL))
|
||||
if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
|
||||
f = MOUNT_SUCCESS;
|
||||
else if (code == CLD_EXITED)
|
||||
f = MOUNT_FAILURE_EXIT_CODE;
|
||||
|
@ -2600,7 +2600,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
assert(s);
|
||||
assert(pid >= 0);
|
||||
|
||||
if (is_clean_exit(code, status, &s->success_status))
|
||||
if (is_clean_exit(code, status, s->type == SERVICE_ONESHOT ? EXIT_CLEAN_COMMAND : EXIT_CLEAN_DAEMON, &s->success_status))
|
||||
f = SERVICE_SUCCESS;
|
||||
else if (code == CLD_EXITED)
|
||||
f = SERVICE_FAILURE_EXIT_CODE;
|
||||
|
@ -2743,7 +2743,7 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
|
||||
s->control_pid = 0;
|
||||
|
||||
if (is_clean_exit(code, status, NULL))
|
||||
if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
|
||||
f = SOCKET_SUCCESS;
|
||||
else if (code == CLD_EXITED)
|
||||
f = SOCKET_FAILURE_EXIT_CODE;
|
||||
|
@ -988,7 +988,7 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
|
||||
s->control_pid = 0;
|
||||
|
||||
if (is_clean_exit(code, status, NULL))
|
||||
if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
|
||||
f = SWAP_SUCCESS;
|
||||
else if (code == CLD_EXITED)
|
||||
f = SWAP_FAILURE_EXIT_CODE;
|
||||
|
@ -137,7 +137,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
s = hashmap_remove(pids, PID_TO_PTR(si.si_pid));
|
||||
if (s) {
|
||||
if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
|
||||
if (!is_clean_exit(si.si_code, si.si_status, EXIT_CLEAN_COMMAND, NULL)) {
|
||||
if (si.si_code == CLD_EXITED)
|
||||
log_error(MOUNT_PATH " for %s exited with exit status %i.", s, si.si_status);
|
||||
else
|
||||
|
@ -3936,7 +3936,7 @@ static void print_status_info(
|
||||
argv = strv_join(p->argv, " ");
|
||||
printf(" Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv));
|
||||
|
||||
good = is_clean_exit(p->code, p->status, NULL);
|
||||
good = is_clean_exit(p->code, p->status, EXIT_CLEAN_DAEMON, NULL);
|
||||
if (!good) {
|
||||
on = ansi_highlight_red();
|
||||
off = ansi_normal();
|
||||
|
@ -827,7 +827,7 @@ static int ask_on_consoles(int argc, char *argv[]) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_clean_exit(status.si_code, status.si_status, NULL))
|
||||
if (!is_clean_exit(status.si_code, status.si_status, EXIT_CLEAN_DAEMON, NULL))
|
||||
log_error("Password agent failed with: %d", status.si_status);
|
||||
|
||||
terminate_agents(pids);
|
||||
|
Loading…
Reference in New Issue
Block a user