mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-02-02 09:47:03 +03:00
Merge pull request #13696 from keszybz/keep-dhcp-on-restart
Add a way to differentiate restart from stop and keep dhcp config on restart
This commit is contained in:
commit
6e2d361d53
@ -85,32 +85,36 @@
|
||||
unless it is empty.</para>
|
||||
|
||||
<para>Processes will first be terminated via <constant>SIGTERM</constant> (unless the signal to send
|
||||
is changed via <varname>KillSignal=</varname>). Optionally, this is immediately followed by a
|
||||
<constant>SIGHUP</constant> (if enabled with <varname>SendSIGHUP=</varname>). If processes still
|
||||
remain after the main process of a unit has exited or the delay configured via the
|
||||
<varname>TimeoutStopSec=</varname> has passed, the termination request is repeated with the
|
||||
<constant>SIGKILL</constant> signal or the signal specified via <varname>FinalKillSignal=</varname>
|
||||
(unless this is disabled via the <varname>SendSIGKILL=</varname> option). See
|
||||
<citerefentry><refentrytitle>kill</refentrytitle><manvolnum>2</manvolnum></citerefentry> for more
|
||||
information.</para>
|
||||
is changed via <varname>KillSignal=</varname> or <varname>RestartKillSignal=</varname>). Optionally,
|
||||
this is immediately followed by a <constant>SIGHUP</constant> (if enabled with
|
||||
<varname>SendSIGHUP=</varname>). If processes still remain after the main process of a unit has
|
||||
exited or the delay configured via the <varname>TimeoutStopSec=</varname> has passed, the termination
|
||||
request is repeated with the <constant>SIGKILL</constant> signal or the signal specified via
|
||||
<varname>FinalKillSignal=</varname> (unless this is disabled via the <varname>SendSIGKILL=</varname>
|
||||
option). See <citerefentry><refentrytitle>kill</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
||||
for more information.</para>
|
||||
|
||||
<para>Defaults to <option>control-group</option>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>KillSignal=</varname></term>
|
||||
<listitem><para>Specifies which signal to use when killing a
|
||||
service. This controls the signal that is sent as first step
|
||||
of shutting down a unit (see above), and is usually followed
|
||||
by <constant>SIGKILL</constant> (see above and below). For a
|
||||
list of valid signals, see
|
||||
<listitem><para>Specifies which signal to use when stopping a service. This controls the signal that
|
||||
is sent as first step of shutting down a unit (see above), and is usually followed by
|
||||
<constant>SIGKILL</constant> (see above and below). For a list of valid signals, see
|
||||
<citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
|
||||
Defaults to <constant>SIGTERM</constant>. </para>
|
||||
Defaults to <constant>SIGTERM</constant>.</para>
|
||||
|
||||
<para>Note that, right after sending the signal specified in
|
||||
this setting, systemd will always send
|
||||
<constant>SIGCONT</constant>, to ensure that even suspended
|
||||
tasks can be terminated cleanly.</para>
|
||||
<para>Note that, right after sending the signal specified in this setting, systemd will always send
|
||||
<constant>SIGCONT</constant>, to ensure that even suspended tasks can be terminated cleanly.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>RestartKillSignal=</varname></term>
|
||||
<listitem><para>Specifies which signal to use when restarting a service. The same as
|
||||
<varname>KillSignal=</varname> described above, with the exception that this setting is used in a
|
||||
restart job. Not set by default, and the value of <varname>KillSignal=</varname> is used.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
@ -876,8 +876,8 @@
|
||||
lease expires. This is contrary to the DHCP specification, but may be the best choice if,
|
||||
e.g., the root filesystem relies on this connection. The setting <literal>dhcp</literal>
|
||||
implies <literal>dhcp-on-stop</literal>, and <literal>yes</literal> implies
|
||||
<literal>dhcp</literal> and <literal>static</literal>. Defaults to
|
||||
<literal>dhcp-on-stop</literal>.</para>
|
||||
<literal>dhcp</literal> and <literal>static</literal>. Defaults to <literal>no</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@ -1568,7 +1568,7 @@
|
||||
<term><varname>SendRelease=</varname></term>
|
||||
<listitem>
|
||||
<para>When true, the DHCPv4 client sends a DHCP release packet when it stops.
|
||||
Defaults to false.</para>
|
||||
Defaults to true.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
@ -477,26 +477,24 @@
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ExecStop=</varname></term>
|
||||
<listitem><para>Commands to execute to stop the service
|
||||
started via <varname>ExecStart=</varname>. This argument takes
|
||||
multiple command lines, following the same scheme as described
|
||||
for <varname>ExecStart=</varname> above. Use of this setting
|
||||
is optional. After the commands configured in this option are
|
||||
run, it is implied that the service is stopped, and any processes
|
||||
remaining for it are terminated
|
||||
according to the <varname>KillMode=</varname> setting (see
|
||||
<listitem><para>Commands to execute to stop the service started via
|
||||
<varname>ExecStart=</varname>. This argument takes multiple command lines, following the same scheme
|
||||
as described for <varname>ExecStart=</varname> above. Use of this setting is optional. After the
|
||||
commands configured in this option are run, it is implied that the service is stopped, and any
|
||||
processes remaining for it are terminated according to the <varname>KillMode=</varname> setting (see
|
||||
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
|
||||
If this option is not specified, the process is terminated by
|
||||
sending the signal specified in <varname>KillSignal=</varname>
|
||||
when service stop is requested. Specifier and environment
|
||||
variable substitution is supported (including
|
||||
If this option is not specified, the process is terminated by sending the signal specified in
|
||||
<varname>KillSignal=</varname> or <varname>RestartKillSignal=</varname> when service stop is
|
||||
requested. Specifier and environment variable substitution is supported (including
|
||||
<varname>$MAINPID</varname>, see above).</para>
|
||||
|
||||
<para>Note that it is usually not sufficient to specify a command for this setting that only asks the service
|
||||
to terminate (for example, by queuing some form of termination signal for it), but does not wait for it to do
|
||||
so. Since the remaining processes of the services are killed according to <varname>KillMode=</varname> and
|
||||
<varname>KillSignal=</varname> as described above immediately after the command exited, this may not result in
|
||||
a clean stop. The specified command should hence be a synchronous operation, not an asynchronous one.</para>
|
||||
<para>Note that it is usually not sufficient to specify a command for this setting that only asks the
|
||||
service to terminate (for example, by sending some form of termination signal to it), but does not
|
||||
wait for it to do so. Since the remaining processes of the services are killed according to
|
||||
<varname>KillMode=</varname> and <varname>KillSignal=</varname> or
|
||||
<varname>RestartKillSignal=</varname> as described above immediately after the command exited, this
|
||||
may not result in a clean stop. The specified command should hence be a synchronous operation, not an
|
||||
asynchronous one.</para>
|
||||
|
||||
<para>Note that the commands specified in <varname>ExecStop=</varname> are only executed when the service
|
||||
started successfully first. They are not invoked if the service was never started at all, or in case its
|
||||
|
@ -80,7 +80,7 @@ _systemd_run() {
|
||||
SendSIGKILL= MemoryLimit= CPUShares= BlockIOWeight= User= Group=
|
||||
DevicePolicy= KillMode= DeviceAllow= BlockIOReadBandwidth=
|
||||
BlockIOWriteBandwidth= BlockIODeviceWeight= Nice= Environment=
|
||||
KillSignal= FinalKillSignal= LimitCPU= LimitFSIZE= LimitDATA=
|
||||
KillSignal= RestartKillSignal= FinalKillSignal= LimitCPU= LimitFSIZE= LimitDATA=
|
||||
LimitSTACK= LimitCORE= LimitRSS= LimitNOFILE= LimitAS= LimitNPROC=
|
||||
LimitMEMLOCK= LimitLOCKS= LimitSIGPENDING= LimitMSGQUEUE=
|
||||
LimitNICE= LimitRTPRIO= LimitRTTIME= PrivateTmp= PrivateDevices=
|
||||
|
@ -35,7 +35,7 @@ _arguments \
|
||||
SendSIGKILL= MemoryLimit= CPUShares= BlockIOWeight= User= Group= \
|
||||
DevicePolicy= KillMode= DeviceAllow= BlockIOReadBandwidth= \
|
||||
BlockIOWriteBandwidth= BlockIODeviceWeight= Nice= Environment= \
|
||||
KillSignal= FinalKillSignal= LimitCPU= LimitFSIZE= LimitDATA= \
|
||||
KillSignal= RestartKillSignal= FinalKillSignal= LimitCPU= LimitFSIZE= LimitDATA= \
|
||||
LimitSTACK= LimitCORE= LimitRSS= LimitNOFILE= LimitAS= LimitNPROC= \
|
||||
LimitMEMLOCK= LimitLOCKS= LimitSIGPENDING= LimitMSGQUEUE= \
|
||||
LimitNICE= LimitRTPRIO= LimitRTTIME= PrivateTmp= PrivateDevices= \
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "sd-bus.h"
|
||||
#include "sd-bus-vtable.h"
|
||||
|
||||
#include "job.h"
|
||||
#include "unit.h"
|
||||
|
||||
extern const sd_bus_vtable bus_job_vtable[];
|
||||
|
||||
|
@ -8,10 +8,28 @@
|
||||
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_kill_mode, kill_mode, KillMode);
|
||||
|
||||
static int property_get_restart_kill_signal(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
KillContext *c = userdata;
|
||||
int s;
|
||||
|
||||
assert(c);
|
||||
|
||||
s = restart_kill_signal(c);
|
||||
return sd_bus_message_append_basic(reply, 'i', &s);
|
||||
}
|
||||
|
||||
const sd_bus_vtable bus_kill_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("KillMode", "s", property_get_kill_mode, offsetof(KillContext, kill_mode), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("KillSignal", "i", bus_property_get_int, offsetof(KillContext, kill_signal), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RestartKillSignal", "i", property_get_restart_kill_signal, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("FinalKillSignal", "i", bus_property_get_int, offsetof(KillContext, final_kill_signal), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("SendSIGKILL", "b", bus_property_get_bool, offsetof(KillContext, send_sigkill), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("SendSIGHUP", "b", bus_property_get_bool, offsetof(KillContext, send_sighup), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@ -21,6 +39,7 @@ const sd_bus_vtable bus_kill_vtable[] = {
|
||||
|
||||
static BUS_DEFINE_SET_TRANSIENT_PARSE(kill_mode, KillMode, kill_mode_from_string);
|
||||
static BUS_DEFINE_SET_TRANSIENT_TO_STRING(kill_signal, "i", int32_t, int, "%" PRIi32, signal_to_string_with_check);
|
||||
static BUS_DEFINE_SET_TRANSIENT_TO_STRING(restart_kill_signal, "i", int32_t, int, "%" PRIi32, signal_to_string_with_check);
|
||||
static BUS_DEFINE_SET_TRANSIENT_TO_STRING(final_kill_signal, "i", int32_t, int, "%" PRIi32, signal_to_string_with_check);
|
||||
static BUS_DEFINE_SET_TRANSIENT_TO_STRING(watchdog_signal, "i", int32_t, int, "%" PRIi32, signal_to_string_with_check);
|
||||
|
||||
@ -51,6 +70,9 @@ int bus_kill_context_set_transient_property(
|
||||
if (streq(name, "KillSignal"))
|
||||
return bus_set_transient_kill_signal(u, name, &c->kill_signal, message, flags, error);
|
||||
|
||||
if (streq(name, "RestartKillSignal"))
|
||||
return bus_set_transient_restart_kill_signal(u, name, &c->restart_kill_signal, message, flags, error);
|
||||
|
||||
if (streq(name, "FinalKillSignal"))
|
||||
return bus_set_transient_final_kill_signal(u, name, &c->final_kill_signal, message, flags, error);
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "sd-bus.h"
|
||||
#include "sd-bus-vtable.h"
|
||||
|
||||
#include "job.h"
|
||||
#include "unit.h"
|
||||
|
||||
extern const sd_bus_vtable bus_unit_vtable[];
|
||||
|
@ -9,6 +9,7 @@ void kill_context_init(KillContext *c) {
|
||||
assert(c);
|
||||
|
||||
c->kill_signal = SIGTERM;
|
||||
/* restart_kill_signal is unset by default and we fall back to kill_signal */
|
||||
c->final_kill_signal = SIGKILL;
|
||||
c->send_sigkill = true;
|
||||
c->send_sighup = false;
|
||||
@ -23,11 +24,13 @@ void kill_context_dump(KillContext *c, FILE *f, const char *prefix) {
|
||||
fprintf(f,
|
||||
"%sKillMode: %s\n"
|
||||
"%sKillSignal: SIG%s\n"
|
||||
"%sRestartKillSignal: SIG%s\n"
|
||||
"%sFinalKillSignal: SIG%s\n"
|
||||
"%sSendSIGKILL: %s\n"
|
||||
"%sSendSIGHUP: %s\n",
|
||||
"%sSendSIGHUP: %s\n",
|
||||
prefix, kill_mode_to_string(c->kill_mode),
|
||||
prefix, signal_to_string(c->kill_signal),
|
||||
prefix, signal_to_string(restart_kill_signal(c)),
|
||||
prefix, signal_to_string(c->final_kill_signal),
|
||||
prefix, yes_no(c->send_sigkill),
|
||||
prefix, yes_no(c->send_sighup));
|
||||
@ -35,20 +38,20 @@ void kill_context_dump(KillContext *c, FILE *f, const char *prefix) {
|
||||
|
||||
static const char* const kill_mode_table[_KILL_MODE_MAX] = {
|
||||
[KILL_CONTROL_GROUP] = "control-group",
|
||||
[KILL_PROCESS] = "process",
|
||||
[KILL_MIXED] = "mixed",
|
||||
[KILL_NONE] = "none"
|
||||
[KILL_PROCESS] = "process",
|
||||
[KILL_MIXED] = "mixed",
|
||||
[KILL_NONE] = "none",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(kill_mode, KillMode);
|
||||
|
||||
static const char* const kill_who_table[_KILL_WHO_MAX] = {
|
||||
[KILL_MAIN] = "main",
|
||||
[KILL_CONTROL] = "control",
|
||||
[KILL_ALL] = "all",
|
||||
[KILL_MAIN_FAIL] = "main-fail",
|
||||
[KILL_MAIN] = "main",
|
||||
[KILL_CONTROL] = "control",
|
||||
[KILL_ALL] = "all",
|
||||
[KILL_MAIN_FAIL] = "main-fail",
|
||||
[KILL_CONTROL_FAIL] = "control-fail",
|
||||
[KILL_ALL_FAIL] = "all-fail"
|
||||
[KILL_ALL_FAIL] = "all-fail",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);
|
||||
|
@ -21,6 +21,7 @@ typedef enum KillMode {
|
||||
struct KillContext {
|
||||
KillMode kill_mode;
|
||||
int kill_signal;
|
||||
int restart_kill_signal;
|
||||
int final_kill_signal;
|
||||
int watchdog_signal;
|
||||
bool send_sigkill;
|
||||
@ -47,3 +48,9 @@ KillMode kill_mode_from_string(const char *s) _pure_;
|
||||
|
||||
const char *kill_who_to_string(KillWho k) _const_;
|
||||
KillWho kill_who_from_string(const char *s) _pure_;
|
||||
|
||||
static inline int restart_kill_signal(const KillContext *c) {
|
||||
if (c->restart_kill_signal != 0)
|
||||
return c->restart_kill_signal;
|
||||
return c->kill_signal;
|
||||
}
|
||||
|
@ -161,6 +161,7 @@ m4_define(`KILL_CONTEXT_CONFIG_ITEMS',
|
||||
$1.SendSIGHUP, config_parse_bool, 0, offsetof($1, kill_context.send_sighup)
|
||||
$1.KillMode, config_parse_kill_mode, 0, offsetof($1, kill_context.kill_mode)
|
||||
$1.KillSignal, config_parse_signal, 0, offsetof($1, kill_context.kill_signal)
|
||||
$1.RestartKillSignal, config_parse_signal, 0, offsetof($1, kill_context.restart_kill_signal)
|
||||
$1.FinalKillSignal, config_parse_signal, 0, offsetof($1, kill_context.final_kill_signal)
|
||||
$1.WatchdogSignal, config_parse_signal, 0, offsetof($1, kill_context.watchdog_signal)'
|
||||
)m4_dnl
|
||||
|
@ -43,8 +43,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_prio);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_affinity);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_exec_secure_bits);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_capability_set);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_kill_signal);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_final_kill_signal);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_exec_mount_flags);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_timer);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_trigger_unit);
|
||||
|
@ -866,6 +866,8 @@ static int state_to_kill_operation(MountState state) {
|
||||
switch (state) {
|
||||
|
||||
case MOUNT_REMOUNTING_SIGTERM:
|
||||
return KILL_RESTART;
|
||||
|
||||
case MOUNT_UNMOUNTING_SIGTERM:
|
||||
return KILL_TERMINATE;
|
||||
|
||||
|
@ -1838,13 +1838,17 @@ fail:
|
||||
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
|
||||
}
|
||||
|
||||
static int state_to_kill_operation(ServiceState state) {
|
||||
static int state_to_kill_operation(Service *s, ServiceState state) {
|
||||
switch (state) {
|
||||
|
||||
case SERVICE_STOP_WATCHDOG:
|
||||
return KILL_WATCHDOG;
|
||||
|
||||
case SERVICE_STOP_SIGTERM:
|
||||
if (unit_has_job_type(UNIT(s), JOB_RESTART))
|
||||
return KILL_RESTART;
|
||||
_fallthrough_;
|
||||
|
||||
case SERVICE_FINAL_SIGTERM:
|
||||
return KILL_TERMINATE;
|
||||
|
||||
@ -1875,7 +1879,7 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
|
||||
r = unit_kill_context(
|
||||
UNIT(s),
|
||||
&s->kill_context,
|
||||
state_to_kill_operation(state),
|
||||
state_to_kill_operation(s, state),
|
||||
s->main_pid,
|
||||
s->control_pid,
|
||||
s->main_pid_alien);
|
||||
@ -2245,7 +2249,7 @@ static void service_enter_restart(Service *s) {
|
||||
|
||||
assert(s);
|
||||
|
||||
if (UNIT(s)->job && UNIT(s)->job->type == JOB_STOP) {
|
||||
if (unit_has_job_type(UNIT(s), JOB_STOP)) {
|
||||
/* Don't restart things if we are going down anyway */
|
||||
log_unit_info(UNIT(s), "Stop job pending for unit, delaying automatic restart.");
|
||||
|
||||
|
@ -2077,6 +2077,16 @@ fail:
|
||||
socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_RESOURCES);
|
||||
}
|
||||
|
||||
static int state_to_kill_operation(Socket *s, SocketState state) {
|
||||
if (state == SOCKET_STOP_PRE_SIGTERM && unit_has_job_type(UNIT(s), JOB_RESTART))
|
||||
return KILL_RESTART;
|
||||
|
||||
if (state == SOCKET_FINAL_SIGTERM)
|
||||
return KILL_TERMINATE;
|
||||
|
||||
return KILL_KILL;
|
||||
}
|
||||
|
||||
static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
|
||||
int r;
|
||||
|
||||
@ -2088,8 +2098,7 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
|
||||
r = unit_kill_context(
|
||||
UNIT(s),
|
||||
&s->kill_context,
|
||||
!IN_SET(state, SOCKET_STOP_PRE_SIGTERM, SOCKET_FINAL_SIGTERM) ?
|
||||
KILL_KILL : KILL_TERMINATE,
|
||||
state_to_kill_operation(s, state),
|
||||
-1,
|
||||
s->control_pid,
|
||||
false);
|
||||
|
@ -712,21 +712,32 @@ static void swap_enter_dead_or_active(Swap *s, SwapResult f) {
|
||||
swap_enter_dead(s, f);
|
||||
}
|
||||
|
||||
static int state_to_kill_operation(Swap *s, SwapState state) {
|
||||
if (state == SWAP_DEACTIVATING_SIGTERM) {
|
||||
if (unit_has_job_type(UNIT(s), JOB_RESTART))
|
||||
return KILL_RESTART;
|
||||
else
|
||||
return KILL_TERMINATE;
|
||||
}
|
||||
|
||||
return KILL_KILL;
|
||||
}
|
||||
|
||||
static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
|
||||
int r;
|
||||
KillOperation kop;
|
||||
|
||||
assert(s);
|
||||
|
||||
if (s->result == SWAP_SUCCESS)
|
||||
s->result = f;
|
||||
|
||||
if (state == SWAP_DEACTIVATING_SIGTERM)
|
||||
kop = KILL_TERMINATE;
|
||||
else
|
||||
kop = KILL_KILL;
|
||||
|
||||
r = unit_kill_context(UNIT(s), &s->kill_context, kop, -1, s->control_pid, false);
|
||||
r = unit_kill_context(UNIT(s),
|
||||
&s->kill_context,
|
||||
state_to_kill_operation(s, state),
|
||||
-1,
|
||||
s->control_pid,
|
||||
false);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -4022,7 +4022,7 @@ bool unit_stop_pending(Unit *u) {
|
||||
* different from unit_inactive_or_pending() which checks both
|
||||
* the current state and for a queued job. */
|
||||
|
||||
return u->job && u->job->type == JOB_STOP;
|
||||
return unit_has_job_type(u, JOB_STOP);
|
||||
}
|
||||
|
||||
bool unit_inactive_or_pending(Unit *u) {
|
||||
@ -4057,12 +4057,7 @@ bool unit_active_or_pending(Unit *u) {
|
||||
bool unit_will_restart_default(Unit *u) {
|
||||
assert(u);
|
||||
|
||||
if (!u->job)
|
||||
return false;
|
||||
if (u->job->type == JOB_START)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return unit_has_job_type(u, JOB_START);
|
||||
}
|
||||
|
||||
bool unit_will_restart(Unit *u) {
|
||||
@ -4691,19 +4686,26 @@ static int log_kill(pid_t pid, int sig, void *userdata) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int operation_to_signal(KillContext *c, KillOperation k) {
|
||||
static int operation_to_signal(const KillContext *c, KillOperation k, bool *noteworthy) {
|
||||
assert(c);
|
||||
|
||||
switch (k) {
|
||||
|
||||
case KILL_TERMINATE:
|
||||
case KILL_TERMINATE_AND_LOG:
|
||||
*noteworthy = false;
|
||||
return c->kill_signal;
|
||||
|
||||
case KILL_RESTART:
|
||||
*noteworthy = false;
|
||||
return restart_kill_signal(c);
|
||||
|
||||
case KILL_KILL:
|
||||
*noteworthy = true;
|
||||
return c->final_kill_signal;
|
||||
|
||||
case KILL_WATCHDOG:
|
||||
*noteworthy = true;
|
||||
return c->watchdog_signal;
|
||||
|
||||
default:
|
||||
@ -4732,16 +4734,16 @@ int unit_kill_context(
|
||||
if (c->kill_mode == KILL_NONE)
|
||||
return 0;
|
||||
|
||||
sig = operation_to_signal(c, k);
|
||||
bool noteworthy;
|
||||
sig = operation_to_signal(c, k, ¬eworthy);
|
||||
if (noteworthy)
|
||||
log_func = log_kill;
|
||||
|
||||
send_sighup =
|
||||
c->send_sighup &&
|
||||
IN_SET(k, KILL_TERMINATE, KILL_TERMINATE_AND_LOG) &&
|
||||
sig != SIGHUP;
|
||||
|
||||
if (k != KILL_TERMINATE || IN_SET(sig, SIGKILL, SIGABRT))
|
||||
log_func = log_kill;
|
||||
|
||||
if (main_pid > 0) {
|
||||
if (log_func)
|
||||
log_func(main_pid, sig, u);
|
||||
|
@ -18,6 +18,7 @@ typedef struct UnitRef UnitRef;
|
||||
typedef enum KillOperation {
|
||||
KILL_TERMINATE,
|
||||
KILL_TERMINATE_AND_LOG,
|
||||
KILL_RESTART,
|
||||
KILL_KILL,
|
||||
KILL_WATCHDOG,
|
||||
_KILL_OPERATION_MAX,
|
||||
@ -842,6 +843,10 @@ const char *unit_label_path(Unit *u);
|
||||
|
||||
int unit_pid_attachable(Unit *unit, pid_t pid, sd_bus_error *error);
|
||||
|
||||
static inline bool unit_has_job_type(Unit *u, JobType type) {
|
||||
return u && u->job && u->job->type == type;
|
||||
}
|
||||
|
||||
/* unit_log_skip is for cases like ExecCondition= where a unit is considered "done"
|
||||
* after some execution, rather than succeeded or failed. */
|
||||
void unit_log_skip(Unit *u, const char *result);
|
||||
|
@ -870,41 +870,6 @@ static int client_send_discover(sd_dhcp_client *client) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int client_send_release(sd_dhcp_client *client) {
|
||||
_cleanup_free_ DHCPPacket *release = NULL;
|
||||
size_t optoffset, optlen;
|
||||
int r;
|
||||
|
||||
assert(client);
|
||||
assert(!IN_SET(client->state, DHCP_STATE_STOPPED));
|
||||
|
||||
r = client_message_init(client, &release, DHCP_RELEASE,
|
||||
&optlen, &optoffset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Fill up release IP and MAC */
|
||||
release->dhcp.ciaddr = client->lease->address;
|
||||
memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len);
|
||||
|
||||
r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0,
|
||||
SD_DHCP_OPTION_END, 0, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dhcp_network_send_udp_socket(client->fd,
|
||||
client->lease->server_address,
|
||||
DHCP_PORT_SERVER,
|
||||
&release->dhcp,
|
||||
sizeof(DHCPMessage) + optoffset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_dhcp_client(client, "RELEASE");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int client_send_request(sd_dhcp_client *client) {
|
||||
_cleanup_free_ DHCPPacket *request = NULL;
|
||||
size_t optoffset, optlen;
|
||||
@ -1929,8 +1894,35 @@ int sd_dhcp_client_start(sd_dhcp_client *client) {
|
||||
|
||||
int sd_dhcp_client_send_release(sd_dhcp_client *client) {
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(client->state != DHCP_STATE_STOPPED, -ESTALE);
|
||||
assert_return(client->lease, -EUNATCH);
|
||||
|
||||
client_send_release(client);
|
||||
_cleanup_free_ DHCPPacket *release = NULL;
|
||||
size_t optoffset, optlen;
|
||||
int r;
|
||||
|
||||
r = client_message_init(client, &release, DHCP_RELEASE, &optlen, &optoffset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Fill up release IP and MAC */
|
||||
release->dhcp.ciaddr = client->lease->address;
|
||||
memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len);
|
||||
|
||||
r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0,
|
||||
SD_DHCP_OPTION_END, 0, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dhcp_network_send_udp_socket(client->fd,
|
||||
client->lease->server_address,
|
||||
DHCP_PORT_SERVER,
|
||||
&release->dhcp,
|
||||
sizeof(DHCPMessage) + optoffset);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_dhcp_client(client, "RELEASE");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -864,10 +864,10 @@ static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_send_release)
|
||||
(void) sd_dhcp_client_send_release(client);
|
||||
|
||||
if (link->dhcp_lease) {
|
||||
if (link->network->dhcp_send_release)
|
||||
(void) sd_dhcp_client_send_release(client);
|
||||
|
||||
r = dhcp_lease_lost(link);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
|
@ -770,8 +770,12 @@ int link_stop_clients(Link *link, bool may_keep_dhcp) {
|
||||
|
||||
dhcp4_release_old_lease(link);
|
||||
|
||||
if (link->dhcp_client && (!may_keep_dhcp || !link->network ||
|
||||
!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP_ON_STOP))) {
|
||||
bool keep_dhcp = may_keep_dhcp &&
|
||||
link->network &&
|
||||
(link->manager->restarting ||
|
||||
FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP_ON_STOP));
|
||||
|
||||
if (link->dhcp_client && !keep_dhcp) {
|
||||
k = sd_dhcp_client_stop(link->dhcp_client);
|
||||
if (k < 0)
|
||||
r = log_link_warning_errno(link, k, "Could not stop DHCPv4 client: %m");
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "ordered-set.h"
|
||||
#include "path-util.h"
|
||||
#include "set.h"
|
||||
#include "signal-util.h"
|
||||
#include "strv.h"
|
||||
#include "sysctl-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
@ -1561,6 +1562,28 @@ static int manager_dirty_handler(sd_event_source *s, void *userdata) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int signal_terminate_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
|
||||
Manager *m = userdata;
|
||||
|
||||
assert(m);
|
||||
m->restarting = false;
|
||||
|
||||
log_debug("Terminate operation initiated.");
|
||||
|
||||
return sd_event_exit(sd_event_source_get_event(s), 0);
|
||||
}
|
||||
|
||||
static int signal_restart_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
|
||||
Manager *m = userdata;
|
||||
|
||||
assert(m);
|
||||
m->restarting = true;
|
||||
|
||||
log_debug("Restart operation initiated.");
|
||||
|
||||
return sd_event_exit(sd_event_source_get_event(s), 0);
|
||||
}
|
||||
|
||||
int manager_new(Manager **ret) {
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
int r;
|
||||
@ -1581,9 +1604,12 @@ int manager_new(Manager **ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR2, -1) >= 0);
|
||||
|
||||
(void) sd_event_set_watchdog(m->event, true);
|
||||
(void) sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
|
||||
(void) sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
|
||||
(void) sd_event_add_signal(m->event, NULL, SIGTERM, signal_terminate_callback, m);
|
||||
(void) sd_event_add_signal(m->event, NULL, SIGINT, signal_terminate_callback, m);
|
||||
(void) sd_event_add_signal(m->event, NULL, SIGUSR2, signal_restart_callback, m);
|
||||
|
||||
r = sd_event_add_post(m->event, NULL, manager_dirty_handler, m);
|
||||
if (r < 0)
|
||||
|
@ -29,6 +29,7 @@ struct Manager {
|
||||
|
||||
bool enumerating:1;
|
||||
bool dirty:1;
|
||||
bool restarting:1;
|
||||
|
||||
Set *dirty_links;
|
||||
|
||||
|
@ -268,13 +268,11 @@ int network_verify(Network *network) {
|
||||
/* CriticalConnection=yes also preserve foreign static configurations. */
|
||||
network->keep_configuration = KEEP_CONFIGURATION_YES;
|
||||
else
|
||||
/* For backward compatibility, we do not release DHCP addresses on manager stop. */
|
||||
network->keep_configuration = KEEP_CONFIGURATION_DHCP_ON_STOP;
|
||||
network->keep_configuration = KEEP_CONFIGURATION_NO;
|
||||
}
|
||||
|
||||
if (network->keep_configuration < 0)
|
||||
/* For backward compatibility, we do not release DHCP addresses on manager stop. */
|
||||
network->keep_configuration = KEEP_CONFIGURATION_DHCP_ON_STOP;
|
||||
network->keep_configuration = KEEP_CONFIGURATION_NO;
|
||||
|
||||
LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses)
|
||||
if (address_section_verify(address) < 0)
|
||||
@ -373,6 +371,7 @@ int network_load_one(Manager *manager, const char *filename) {
|
||||
.dhcp_use_routes = true,
|
||||
/* NOTE: this var might be overwritten by network_apply_anonymize_if_set */
|
||||
.dhcp_send_hostname = true,
|
||||
.dhcp_send_release = true,
|
||||
/* To enable/disable RFC7844 Anonymity Profiles */
|
||||
.dhcp_anonymize = false,
|
||||
.dhcp_route_metric = DHCP_ROUTE_METRIC,
|
||||
|
@ -1355,15 +1355,12 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
|
||||
static int bus_append_kill_property(sd_bus_message *m, const char *field, const char *eq) {
|
||||
|
||||
if (streq(field, "KillMode"))
|
||||
|
||||
return bus_append_string(m, field, eq);
|
||||
|
||||
if (STR_IN_SET(field, "SendSIGHUP", "SendSIGKILL"))
|
||||
|
||||
return bus_append_parse_boolean(m, field, eq);
|
||||
|
||||
if (STR_IN_SET(field, "KillSignal", "FinalKillSignal", "WatchdogSignal"))
|
||||
|
||||
if (STR_IN_SET(field, "KillSignal", "RestartKillSignal", "FinalKillSignal", "WatchdogSignal"))
|
||||
return bus_append_signal_from_string(m, field, eq);
|
||||
|
||||
return 0;
|
||||
|
@ -106,9 +106,9 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
printf("Test11: (Start/stop job ordering, execution cycle)\n");
|
||||
assert_se(manager_add_job(m, JOB_START, i, JOB_FAIL, NULL, NULL, &j) == 0);
|
||||
assert_se(a->job && a->job->type == JOB_STOP);
|
||||
assert_se(d->job && d->job->type == JOB_STOP);
|
||||
assert_se(b->job && b->job->type == JOB_START);
|
||||
assert_se(unit_has_job_type(a, JOB_STOP));
|
||||
assert_se(unit_has_job_type(d, JOB_STOP));
|
||||
assert_se(unit_has_job_type(b, JOB_START));
|
||||
manager_dump_jobs(m, stdout, "\t");
|
||||
|
||||
printf("Load6:\n");
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "job.h"
|
||||
#include "service.h"
|
||||
#include "unit.h"
|
||||
|
||||
|
@ -19,6 +19,14 @@ systemd-run --unit=four -p Type=exec /bin/sleep infinity
|
||||
! systemd-run --unit=five -p Type=exec -p User=idontexist /bin/sleep infinity
|
||||
! systemd-run --unit=six -p Type=exec /tmp/brokenbinary
|
||||
|
||||
systemd-run --unit=seven -p KillSignal=SIGTERM -p RestartKillSignal=SIGINT -p Type=exec /bin/sleep infinity
|
||||
# Both TERM and SIGINT happen to have the same number on all architectures
|
||||
test $(systemctl show --value -p KillSignal seven.service) -eq 15
|
||||
test $(systemctl show --value -p RestartKillSignal seven.service) -eq 2
|
||||
|
||||
systemctl restart seven.service
|
||||
systemctl stop seven.service
|
||||
|
||||
systemd-analyze log-level info
|
||||
|
||||
echo OK > /testok
|
||||
|
@ -185,6 +185,7 @@ RequiresMountsFor=
|
||||
Requisite=
|
||||
Restart=
|
||||
RestartForceExitStatus=
|
||||
RestartKillSignal=
|
||||
RestartPreventExitStatus=
|
||||
RestartSec=
|
||||
ReusePort=
|
||||
|
@ -42,6 +42,7 @@ SystemCallArchitectures=native
|
||||
SystemCallErrorNumber=EPERM
|
||||
SystemCallFilter=@system-service
|
||||
Type=notify
|
||||
RestartKillSignal=SIGUSR2
|
||||
User=systemd-network
|
||||
WatchdogSec=3min
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user