1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-22 06:50:18 +03:00

execute: make kill mode configurable

This commit is contained in:
Lennart Poettering 2010-04-08 00:52:14 +02:00
parent 09082a94b6
commit 50159e6a77
9 changed files with 125 additions and 27 deletions

View File

@ -174,13 +174,19 @@ int cgroup_bonding_kill(CGroupBonding *b, int sig) {
int r;
Set *s;
bool done;
bool killed = false;
assert(b);
assert(sig > 0);
if (!b->only_us)
return -EAGAIN;
if (!(s = set_new(trivial_hash_func, trivial_compare_func)))
return -ENOMEM;
log_debug("Killing processes from process group %s:%s", b->controller, b->path);
do {
void *iterator;
pid_t pid;
@ -208,6 +214,7 @@ int cgroup_bonding_kill(CGroupBonding *b, int sig) {
break;
}
killed = true;
done = false;
if ((r = set_put(s, INT_TO_PTR(pid))) < 0)
@ -235,20 +242,29 @@ int cgroup_bonding_kill(CGroupBonding *b, int sig) {
} while (!done && r >= 0);
set_free(s);
return r;
if (r < 0)
return r;
return killed ? 0 : -ESRCH;
}
int cgroup_bonding_kill_list(CGroupBonding *first, int sig) {
CGroupBonding *b;
int r = -EAGAIN;
LIST_FOREACH(by_unit, b, first) {
int r;
if ((r = cgroup_bonding_kill(b, sig)) < 0) {
if (r == -EAGAIN || -ESRCH)
continue;
if ((r = cgroup_bonding_kill(b, sig)) < 0)
return r;
}
return 0;
}
return 0;
return r;
}
/* Returns 1 if the group is empty, 0 if it is not, -EAGAIN if we

View File

@ -37,9 +37,6 @@ struct CGroupBonding {
struct cgroup *cgroup;
/* When shutting down, kill all tasks? */
bool kill_all:1;
/* When shutting down, remove cgroup? */
bool clean_up:1;

View File

@ -979,6 +979,32 @@ static int config_parse_sysv_priority(
return 0;
}
static int config_parse_kill_mode(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
const char *rvalue,
void *data,
void *userdata) {
KillMode *m = data, x;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if ((x = kill_mode_from_string(rvalue)) < 0) {
log_error("[%s:%u] Failed to parse kill mode specifier: %s", filename, line, rvalue);
return -EBADMSG;
}
*m = x;
return 0;
}
#define FOLLOW_MAX 8
static int open_follow(char **filename, FILE **_f, Set *names, char **_id) {
@ -1177,6 +1203,7 @@ static int load_from_path(Unit *u, const char *path, UnitLoadState *new_state) {
{ "RootDirectoryStartOnly", config_parse_bool, &u->service.root_directory_start_only, "Service" },
{ "ValidNoProcess", config_parse_bool, &u->service.valid_no_process, "Service" },
{ "SysVStartPriority", config_parse_sysv_priority, &u->service.sysv_start_priority, "Service" },
{ "KillMode", config_parse_kill_mode, &u->service.kill_mode, "Service" },
EXEC_CONTEXT_CONFIG_ITEMS(u->service.exec_context, "Service"),
{ "ListenStream", config_parse_listen, &u->socket, "Socket" },
@ -1192,6 +1219,7 @@ static int load_from_path(Unit *u, const char *path, UnitLoadState *new_state) {
{ "ExecStopPost", config_parse_exec, u->socket.exec_command+SOCKET_EXEC_STOP_POST, "Socket" },
{ "DirectoryMode", config_parse_mode, &u->socket.directory_mode, "Socket" },
{ "SocketMode", config_parse_mode, &u->socket.socket_mode, "Socket" },
{ "KillMode", config_parse_kill_mode, &u->socket.kill_mode, "Socket" },
EXEC_CONTEXT_CONFIG_ITEMS(u->socket.exec_context, "Socket"),
EXEC_CONTEXT_CONFIG_ITEMS(u->automount.exec_context, "Automount"),

View File

@ -700,8 +700,12 @@ static int service_init(Unit *u, UnitLoadState *new_state) {
s->sysv_start_priority = -1;
s->permissions_start_only = false;
s->root_directory_start_only = false;
s->valid_no_process = false;
s->kill_mode = 0;
s->sysv_has_lsb = false;
s->main_pid = s->control_pid = 0;
s->main_pid_known = false;
s->failure = false;
RATELIMIT_INIT(s->ratelimit, 10*USEC_PER_SEC, 5);
@ -755,11 +759,13 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
"%sPermissionsStartOnly: %s\n"
"%sRootDirectoryStartOnly: %s\n"
"%sValidNoProcess: %s\n"
"%sKillMode: %s\n"
"%sType: %s\n",
prefix, service_state_to_string(s->state),
prefix, yes_no(s->permissions_start_only),
prefix, yes_no(s->root_directory_start_only),
prefix, yes_no(s->valid_no_process),
prefix, kill_mode_to_string(s->kill_mode),
prefix, service_type_to_string(s->type));
if (s->pid_file)
@ -1154,23 +1160,34 @@ static void service_enter_signal(Service *s, ServiceState state, bool success) {
sig = (state == SERVICE_STOP_SIGTERM || state == SERVICE_FINAL_SIGTERM) ? SIGTERM : SIGKILL;
r = 0;
if (s->main_pid > 0) {
if (kill(s->main_pid, sig) < 0 && errno != ESRCH)
r = -errno;
else
if (s->kill_mode == KILL_CONTROL_GROUP) {
if ((r = cgroup_bonding_kill_list(UNIT(s)->meta.cgroup_bondings, sig)) < 0) {
if (r != -EAGAIN && r != -ESRCH)
goto fail;
} else
sent = true;
}
if (s->control_pid > 0) {
if (kill(s->control_pid, sig) < 0 && errno != ESRCH)
r = -errno;
else
sent = true;
}
if (!sent) {
r = 0;
if (s->main_pid > 0) {
if (kill(s->kill_mode == KILL_PROCESS ? s->main_pid : -s->main_pid, sig) < 0 && errno != ESRCH)
r = -errno;
else
sent = true;
}
if (r < 0)
goto fail;
if (s->control_pid > 0) {
if (kill(s->kill_mode == KILL_PROCESS ? s->control_pid : -s->control_pid, sig) < 0 && errno != ESRCH)
r = -errno;
else
sent = true;
}
if (r < 0)
goto fail;
}
}
service_set_state(s, state);
@ -1538,7 +1555,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
s->exec_command[SERVICE_EXEC_START]->exec_status = s->main_exec_status;
}
log_debug("%s: main process exited, code=%s status=%i", unit_id(u), sigchld_code_to_string(code), status);
log_debug("%s: main process exited, code=%s, status=%i", unit_id(u), sigchld_code_to_string(code), status);
/* The service exited, so the service is officially
* gone. */

View File

@ -94,6 +94,8 @@ struct Service {
ServiceState state;
KillMode kill_mode;
ExecStatus main_exec_status;
ExecCommand *control_command;

View File

@ -109,6 +109,9 @@ static int socket_init(Unit *u, UnitLoadState *new_state) {
s->timeout_usec = DEFAULT_TIMEOUT_USEC;
s->directory_mode = 0755;
s->socket_mode = 0666;
s->kill_mode = 0;
s->failure = false;
s->control_pid = 0;
exec_context_init(&s->exec_context);
if ((r = unit_load_fragment(u, new_state)) < 0)
@ -183,11 +186,13 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
"%sSocket State: %s\n"
"%sBindIPv6Only: %s\n"
"%sBacklog: %u\n"
"%sKillMode: %s\n"
"%sSocketMode: %04o\n"
"%sDirectoryMode: %04o\n",
prefix, state_string_table[s->state],
prefix, yes_no(s->bind_ipv6_only),
prefix, s->backlog,
prefix, kill_mode_to_string(s->kill_mode),
prefix, s->socket_mode,
prefix, s->directory_mode);
@ -471,13 +476,25 @@ static void socket_enter_signal(Socket *s, SocketState state, bool success) {
if (s->control_pid > 0) {
int sig;
bool sent = false;
sig = (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_STOP_POST_SIGTERM) ? SIGTERM : SIGKILL;
if (kill(s->control_pid, sig) < 0 && errno != ESRCH) {
r = -errno;
goto fail;
if (s->kill_mode == KILL_CONTROL_GROUP) {
if ((r = cgroup_bonding_kill_list(UNIT(s)->meta.cgroup_bondings, sig)) < 0) {
if (r != -EAGAIN && r != -ESRCH)
goto fail;
} else
sent = true;
}
if (!sent)
if (kill(s->kill_mode == KILL_PROCESS ? s->control_pid : -s->control_pid, sig) < 0 && errno != ESRCH) {
r = -errno;
goto fail;
}
}
socket_set_state(s, state);

View File

@ -89,6 +89,8 @@ struct Socket {
SocketState state;
KillMode kill_mode;
ExecCommand* control_command;
pid_t control_pid;

8
unit.c
View File

@ -1439,3 +1439,11 @@ static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
};
DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);
static const char* const kill_mode_table[_KILL_MODE_MAX] = {
[KILL_PROCESS] = "process",
[KILL_PROCESS_GROUP] = "process-group",
[KILL_CONTROL_GROUP] = "control-group"
};
DEFINE_STRING_TABLE_LOOKUP(kill_mode, KillMode);

15
unit.h
View File

@ -43,6 +43,14 @@ typedef enum UnitDependency UnitDependency;
#define DEFAULT_TIMEOUT_USEC (20*USEC_PER_SEC)
#define DEFAULT_RESTART_USEC (100*USEC_PER_MSEC)
typedef enum KillMode {
KILL_CONTROL_GROUP = 0,
KILL_PROCESS_GROUP,
KILL_PROCESS,
_KILL_MODE_MAX,
_KILL_MODE_INVALID = -1
} KillMode;
enum UnitType {
UNIT_SERVICE = 0,
UNIT_TIMER,
@ -53,7 +61,7 @@ enum UnitType {
UNIT_AUTOMOUNT,
UNIT_SNAPSHOT,
_UNIT_TYPE_MAX,
_UNIT_TYPE_INVALID = -1,
_UNIT_TYPE_INVALID = -1
};
enum UnitLoadState {
@ -314,6 +322,8 @@ int set_unit_path(const char *p);
char *unit_name_escape_path(const char *path, const char *suffix);
char *unit_dbus_path(Unit *u);
const char *unit_type_to_string(UnitType i);
UnitType unit_type_from_string(const char *s);
@ -326,6 +336,7 @@ UnitActiveState unit_active_state_from_string(const char *s);
const char *unit_dependency_to_string(UnitDependency i);
UnitDependency unit_dependency_from_string(const char *s);
char *unit_dbus_path(Unit *u);
const char *kill_mode_to_string(KillMode k);
KillMode kill_mode_from_string(const char *s);
#endif