summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2016-04-29 14:27:04 -0400
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2016-04-29 14:27:04 -0400
commit1c5ed0e2b4923b12be52c9c3e8f43682403dcf32 (patch)
treed80c372d5327113b7bd5321b877f816bb57259f6
parent313fe66fbd0cd3d62566edece7944d6cf45b1b21 (diff)
parentf9bf1b8fee76d4ae2e1676efeecf492493bf67ba (diff)
Merge pull request #3148 from poettering/trigger
core: introduce activation rate limit and parse nice levels and close sockets properly
-rw-r--r--TODO10
-rw-r--r--catalog/systemd.be.catalog2
-rw-r--r--catalog/systemd.be@latin.catalog2
-rw-r--r--catalog/systemd.catalog2
-rw-r--r--catalog/systemd.da.catalog2
-rw-r--r--catalog/systemd.fr.catalog2
-rw-r--r--catalog/systemd.hu.catalog2
-rw-r--r--catalog/systemd.it.catalog2
-rw-r--r--catalog/systemd.ko.catalog2
-rw-r--r--catalog/systemd.pl.catalog2
-rw-r--r--catalog/systemd.pt_BR.catalog2
-rw-r--r--catalog/systemd.ru.catalog2
-rw-r--r--catalog/systemd.sr.catalog2
-rw-r--r--catalog/systemd.zh_CN.catalog2
-rw-r--r--catalog/systemd.zh_TW.catalog2
-rw-r--r--configure.ac2
-rw-r--r--hwdb/60-keyboard.hwdb1
-rw-r--r--man/journald.conf.xml6
-rw-r--r--man/systemd-system.conf.xml6
-rw-r--r--man/systemd.exec.xml38
-rw-r--r--man/systemd.socket.xml16
-rw-r--r--man/systemd.unit.xml13
-rw-r--r--src/basic/missing.h4
-rw-r--r--src/basic/rlimit-util.c52
-rw-r--r--src/core/dbus-manager.c3
-rw-r--r--src/core/dbus-socket.c2
-rw-r--r--src/core/dbus-unit.c3
-rw-r--r--src/core/load-fragment-gperf.gperf.m45
-rw-r--r--src/core/main.c4
-rw-r--r--src/core/service.c34
-rw-r--r--src/core/service.h1
-rw-r--r--src/core/socket.c81
-rw-r--r--src/core/socket.h3
-rw-r--r--src/core/system.conf2
-rw-r--r--src/core/unit.c14
-rw-r--r--src/core/user.conf2
-rw-r--r--src/journal/journald-gperf.gperf2
-rw-r--r--src/journal/journald.conf2
-rw-r--r--src/test/test-rlimit-util.c12
39 files changed, 224 insertions, 122 deletions
diff --git a/TODO b/TODO
index f088cac5b7..57d731b46d 100644
--- a/TODO
+++ b/TODO
@@ -40,8 +40,6 @@ Features:
* rework fopen_temporary() to make use of open_tmpfile_linkable() (problem: the
kernel doesn't support linkat() that replaces existing files, currently)
-* journalctl -f --no-tail fails for Lennart
-
* check if DeviceAllow= should split first, resolve specifiers later
* transient units: don't bother with actually setting unit properties, we
@@ -78,11 +76,9 @@ Features:
* PID1: find a way how we can reload unit file configuration for
specific units only, without reloading the whole of systemd
-* add an explicit parser for LimitNICE= and LimitRTPRIO= that verifies
+* add an explicit parser for LimitRTPRIO= that verifies
the specified range and generates sane error messages for incorrect
- specifications. Also, for LimitNICE= maybe introduce a syntax such
- as "+5" or "-7" in order to make the limits more readable as they
- are otherwise shifted by 20.
+ specifications.
* do something about "/control" subcgroups in the unified cgroup hierarchy
@@ -249,7 +245,7 @@ Features:
CAP_NET_ADMIN is set, more than the loopback device is defined, even
when it is otherwise off
-* MessageQueueMessageSize= should use parse_iec_size().
+* MessageQueueMessageSize= (and suchlike) should use parse_iec_size().
* "busctl status" works only as root on dbus1, since we cannot read
/proc/$PID/exe
diff --git a/catalog/systemd.be.catalog b/catalog/systemd.be.catalog
index be081d6efc..051f49492f 100644
--- a/catalog/systemd.be.catalog
+++ b/catalog/systemd.be.catalog
@@ -53,7 +53,7 @@ Documentation: man:journald.conf(5)
Паведамленні іншых сэрвісаў засталіся.
Мяжа, пасля якой паведамленні будуць адкінуты, наладжваецца з
-дапамогай RateLimitInterval= і RateLimitBurst= у файле
+дапамогай RateLimitIntervalSec= і RateLimitBurst= у файле
/etc/systemd/journald.conf. Глядзіце journald.conf(5) для дэталей.
-- e9bf28e6e834481bb6f48f548ad13606
diff --git a/catalog/systemd.be@latin.catalog b/catalog/systemd.be@latin.catalog
index 382fdb8b04..6ab361aafb 100644
--- a/catalog/systemd.be@latin.catalog
+++ b/catalog/systemd.be@latin.catalog
@@ -53,7 +53,7 @@ Majcie na ŭvazie, što byli adkinuty paviedamliennia toĺki hetaha servisu.
Paviedamlienni inšych servisaŭ zastalisia.
Miaža, paslia jakoj paviedamlienni buduć adkinuty, naladžvajecca z
-dapamohaj RateLimitInterval= i RateLimitBurst= u fajlie
+dapamohaj RateLimitIntervalSec= i RateLimitBurst= u fajlie
/etc/systemd/journald.conf. Hliadzicie journald.conf(5) dlia detaliej.
-- e9bf28e6e834481bb6f48f548ad13606
diff --git a/catalog/systemd.catalog b/catalog/systemd.catalog
index 077f182a5a..90929bca6d 100644
--- a/catalog/systemd.catalog
+++ b/catalog/systemd.catalog
@@ -66,7 +66,7 @@ Note that only messages from the service in question have been
dropped, other services' messages are unaffected.
The limits controlling when messages are dropped may be configured
-with RateLimitInterval= and RateLimitBurst= in
+with RateLimitIntervalSec= and RateLimitBurst= in
/etc/systemd/journald.conf. See journald.conf(5) for details.
-- e9bf28e6e834481bb6f48f548ad13606
diff --git a/catalog/systemd.da.catalog b/catalog/systemd.da.catalog
index bd4d742d8a..093e8139da 100644
--- a/catalog/systemd.da.catalog
+++ b/catalog/systemd.da.catalog
@@ -52,7 +52,7 @@ Kun beskeder fra omtalte service er smidt væk. Beskeder fra andre
services er ikke påvirket.
Grænsen for hvornår beskeder bliver smidt væk kan konfigureres
-med RateLimitInterval= og RateLimitBurst= i
+med RateLimitIntervalSec= og RateLimitBurst= i
/etc/systemd/journald.conf. Se journald.conf(5) for detaljer herom.
-- e9bf28e6e834481bb6f48f548ad13606
diff --git a/catalog/systemd.fr.catalog b/catalog/systemd.fr.catalog
index 03a457786f..d71c2902d7 100644
--- a/catalog/systemd.fr.catalog
+++ b/catalog/systemd.fr.catalog
@@ -51,7 +51,7 @@ Notez que seuls des messages de ce service ont été évincés, les messages des
autres services ne sont pas affectés.
Les limites définissant ce comportement peuvent être configurées avec les
-paramètres RateLimitInterval= et RateLimitBurst= dans le fichier
+paramètres RateLimitIntervalSec= et RateLimitBurst= dans le fichier
/etc/systemd/journald.conf. Voir journald.conf(5) pour plus de détails.
-- e9bf28e6e834481bb6f48f548ad13606
diff --git a/catalog/systemd.hu.catalog b/catalog/systemd.hu.catalog
index 30d76916cc..68e8c2572e 100644
--- a/catalog/systemd.hu.catalog
+++ b/catalog/systemd.hu.catalog
@@ -51,7 +51,7 @@ Ne feledje, hogy csak a kérdéses szolgáltatás üzenetei kerültek eldobásra
más szolgáltatások üzeneteit ez nem befolyásolja.
Az üzenetek eldobását vezérlő korlátok az /etc/systemd/journald.conf
-RateLimitInterval= és RateLimitBurst= beállításaival adhatók meg.
+RateLimitIntervalSec= és RateLimitBurst= beállításaival adhatók meg.
Részletekért lásd a journald.conf(5) man oldalt.
-- e9bf28e6e834481bb6f48f548ad13606
diff --git a/catalog/systemd.it.catalog b/catalog/systemd.it.catalog
index 861b92b74a..b6fca48221 100644
--- a/catalog/systemd.it.catalog
+++ b/catalog/systemd.it.catalog
@@ -46,7 +46,7 @@ Solo i messaggi del servizio indicato sono stati
eliminati, i messaggi degli altri servizi rimangono invariati.
I limiti oltre i quali i messaggi si eliminano si configurano
-con RateLimitInterval= e RateLimitBurst= in
+con RateLimitIntervalSec= e RateLimitBurst= in
/etc/systemd/journald.conf. Vedi journald.conf(5) per maggiori informazioni.
-- e9bf28e6e834481bb6f48f548ad13606
diff --git a/catalog/systemd.ko.catalog b/catalog/systemd.ko.catalog
index 3c3535a94c..2fc6b60b1b 100644
--- a/catalog/systemd.ko.catalog
+++ b/catalog/systemd.ko.catalog
@@ -55,7 +55,7 @@ Documentation: man:journald.conf(5)
다른 서비스의 메시지에는 영향을 주지 않습니다.
메시지 거절 제어 제한 값은 /etc/systemd/journald.conf 의
-RateLimitInterval= 변수와 RateLimitBurst= 변수로 설정합니다.
+RateLimitIntervalSec= 변수와 RateLimitBurst= 변수로 설정합니다.
자세한 내용은 ournald.conf(5)를 살펴보십시오.
-- e9bf28e6e834481bb6f48f548ad13606
diff --git a/catalog/systemd.pl.catalog b/catalog/systemd.pl.catalog
index 0d2e3d22cf..d8059e93cd 100644
--- a/catalog/systemd.pl.catalog
+++ b/catalog/systemd.pl.catalog
@@ -69,7 +69,7 @@ Proszę zauważyć, że tylko komunikaty z danej usługi zostały pominięte. Ni
to wpływu na komunikaty innych usług.
Ograniczenia kontrolujące pomijanie komunikatów mogą być konfigurowane
-za pomocą opcji RateLimitInterval= i RateLimitBurst= w pliku
+za pomocą opcji RateLimitIntervalSec= i RateLimitBurst= w pliku
/etc/systemd/journald.conf. Strona journald.conf(5) zawiera więcej informacji.
-- e9bf28e6e834481bb6f48f548ad13606
diff --git a/catalog/systemd.pt_BR.catalog b/catalog/systemd.pt_BR.catalog
index d9716e30f7..8b856e8355 100644
--- a/catalog/systemd.pt_BR.catalog
+++ b/catalog/systemd.pt_BR.catalog
@@ -53,7 +53,7 @@ Note que apenas mensagens de um serviço em questão foram descartadas; outras
mensagens dos serviços não foram afetadas.
Os controles de limites de quando as mensagens são descartadas pode ser
-configurado com RateLimitInterval= e RateLimitBurst= no
+configurado com RateLimitIntervalSec= e RateLimitBurst= no
/etc/systemd/journald.conf. Veja journald.conf(5) para detalhes.
-- e9bf28e6e834481bb6f48f548ad13606
diff --git a/catalog/systemd.ru.catalog b/catalog/systemd.ru.catalog
index eedbb8aa9c..e56dbe3acc 100644
--- a/catalog/systemd.ru.catalog
+++ b/catalog/systemd.ru.catalog
@@ -76,7 +76,7 @@ Documentation: man:journald.conf(5)
сообщения других служб не затронуты.
Предел, после которого служба журнала начинает игнорировать сообщения,
-настраивается параметрами RateLimitInterval= и RateLimitBurst= в файле
+настраивается параметрами RateLimitIntervalSec= и RateLimitBurst= в файле
/etc/systemd/journald.conf. Подробности смотрите на странице руководства
journald.conf(5).
diff --git a/catalog/systemd.sr.catalog b/catalog/systemd.sr.catalog
index cf700c477b..cc689b7956 100644
--- a/catalog/systemd.sr.catalog
+++ b/catalog/systemd.sr.catalog
@@ -52,7 +52,7 @@ Documentation: man:journald.conf(5)
услуге нису захваћене овим.
Ограничења која подешавају начин на који се поруке одбацују се могу подесити
-помоћу „RateLimitInterval=“ и „RateLimitBurst=“ параметара унутар датотеке
+помоћу „RateLimitIntervalSec=“ и „RateLimitBurst=“ параметара унутар датотеке
/etc/systemd/journald.conf. Погледајте journald.conf(5) за појединости.
-- e9bf28e6e834481bb6f48f548ad13606
diff --git a/catalog/systemd.zh_CN.catalog b/catalog/systemd.zh_CN.catalog
index 38639109e4..ed59fc9250 100644
--- a/catalog/systemd.zh_CN.catalog
+++ b/catalog/systemd.zh_CN.catalog
@@ -50,7 +50,7 @@ Documentation: man:journald.conf(5)
请注意只有由有问题的服务传来的消息被丢弃,
其它服务的消息不受影响。
-可以在 /etc/systemd/journald.conf 中设定 RateLimitInterval=
+可以在 /etc/systemd/journald.conf 中设定 RateLimitIntervalSec=
以及 RateLimitBurst = 的值以控制丢弃信息的限制。
请参见 journald.conf(5) 以了解详情。
diff --git a/catalog/systemd.zh_TW.catalog b/catalog/systemd.zh_TW.catalog
index 027ffe44e5..aa5004db08 100644
--- a/catalog/systemd.zh_TW.catalog
+++ b/catalog/systemd.zh_TW.catalog
@@ -53,7 +53,7 @@ Documentation: man:journald.conf(5)
其他服務的訊息則不受影響。
可以在 /etc/systemd/journald.conf 中設定
-RateLimitInterval= 以及 RateLimitBurst=
+RateLimitIntervalSec= 以及 RateLimitBurst=
來控制當訊息要開始被丟棄時的限制。參見 journald.conf(5) 以獲得更多資訊。
-- e9bf28e6e834481bb6f48f548ad13606
diff --git a/configure.ac b/configure.ac
index d4e8ab6664..1d668623a4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -336,7 +336,7 @@ AC_CHECK_DECLS([IFLA_INET6_ADDR_GEN_MODE,
IFLA_BRIDGE_VLAN_INFO,
IFLA_BRPORT_PROXYARP,
IFLA_BRPORT_LEARNING_SYNC,
- IFLA_BR_PRIORITY,
+ IFLA_BR_VLAN_DEFAULT_PVID,
NDA_IFINDEX,
IFA_FLAGS],
[], [], [[
diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb
index 48665ca744..fd49b03493 100644
--- a/hwdb/60-keyboard.hwdb
+++ b/hwdb/60-keyboard.hwdb
@@ -495,6 +495,7 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pnHP*ProBook*4*:pvr*
# HP ZBook
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPZBook*:pvr*
KEYBOARD_KEY_81=f20 # Fn+F8; Microphone mute button, should be micmute
+
# HP Folio 1040g2
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPEliteBookFolio1040G2:pvr*
KEYBOARD_KEY_81=f20 # Fn+F8; Microphone mute button, should be micmute
diff --git a/man/journald.conf.xml b/man/journald.conf.xml
index a9690e8138..3964cd6bc5 100644
--- a/man/journald.conf.xml
+++ b/man/journald.conf.xml
@@ -148,12 +148,12 @@
</varlistentry>
<varlistentry>
- <term><varname>RateLimitInterval=</varname></term>
+ <term><varname>RateLimitIntervalSec=</varname></term>
<term><varname>RateLimitBurst=</varname></term>
<listitem><para>Configures the rate limiting that is applied
to all messages generated on the system. If, in the time
- interval defined by <varname>RateLimitInterval=</varname>,
+ interval defined by <varname>RateLimitIntervalSec=</varname>,
more messages than specified in
<varname>RateLimitBurst=</varname> are logged by a service,
all further messages within the interval are dropped until the
@@ -162,7 +162,7 @@
per-service, so that two services which log do not interfere
with each other's limits. Defaults to 1000 messages in 30s.
The time specification for
- <varname>RateLimitInterval=</varname> may be specified in the
+ <varname>RateLimitIntervalSec=</varname> may be specified in the
following units: <literal>s</literal>, <literal>min</literal>,
<literal>h</literal>, <literal>ms</literal>,
<literal>us</literal>. To turn off any kind of rate limiting,
diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
index edc6df914a..8833e73c72 100644
--- a/man/systemd-system.conf.xml
+++ b/man/systemd-system.conf.xml
@@ -271,16 +271,16 @@
</varlistentry>
<varlistentry>
- <term><varname>DefaultStartLimitInterval=</varname></term>
+ <term><varname>DefaultStartLimitIntervalSec=</varname></term>
<term><varname>DefaultStartLimitBurst=</varname></term>
<listitem><para>Configure the default unit start rate
limiting, as configured per-service by
- <varname>StartLimitInterval=</varname> and
+ <varname>StartLimitIntervalSec=</varname> and
<varname>StartLimitBurst=</varname>. See
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details on the per-service settings.
- <varname>DefaultStartLimitInterval=</varname> defaults to
+ <varname>DefaultStartLimitIntervalSec=</varname> defaults to
10s. <varname>DefaultStartLimitBurst=</varname> defaults to
5.</para></listitem>
</varlistentry>
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index 2d0fb63f1d..2a93760428 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -629,27 +629,23 @@
<term><varname>LimitNICE=</varname></term>
<term><varname>LimitRTPRIO=</varname></term>
<term><varname>LimitRTTIME=</varname></term>
- <listitem><para>These settings set both soft and hard limits
- of various resources for executed processes. See
- <citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>
- for details. The resource limit is possible to specify in two formats,
- <option>value</option> to set soft and hard limits to the same value,
- or <option>soft:hard</option> to set both limits individually (e.g. LimitAS=4G:16G).
- Use the string <varname>infinity</varname> to
- configure no limit on a specific resource. The multiplicative
- suffixes K (=1024), M (=1024*1024) and so on for G, T, P and E
- may be used for resource limits measured in bytes
- (e.g. LimitAS=16G). For the limits referring to time values,
- the usual time units ms, s, min, h and so on may be used (see
- <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>
- for details). Note that if no time unit is specified for
- <varname>LimitCPU=</varname> the default unit of seconds is
- implied, while for <varname>LimitRTTIME=</varname> the default
- unit of microseconds is implied. Also, note that the effective
- granularity of the limits might influence their
- enforcement. For example, time limits specified for
- <varname>LimitCPU=</varname> will be rounded up implicitly to
- multiples of 1s.</para>
+ <listitem><para>Set soft and hard limits on various resources for executed processes. See
+ <citerefentry><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry> for details on
+ the resource limit concept. Resource limits may be specified in two formats: either as single value to set a
+ specific soft and hard limit to the same value, or as colon-separated pair <option>soft:hard</option> to set
+ both limits individually (e.g. <literal>LimitAS=4G:16G</literal>). Use the string <varname>infinity</varname>
+ to configure no limit on a specific resource. The multiplicative suffixes K, M, G, T, P and E (to the base
+ 1024) may be used for resource limits measured in bytes (e.g. LimitAS=16G). For the limits referring to time
+ values, the usual time units ms, s, min, h and so on may be used (see
+ <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
+ details). Note that if no time unit is specified for <varname>LimitCPU=</varname> the default unit of seconds
+ is implied, while for <varname>LimitRTTIME=</varname> the default unit of microseconds is implied. Also, note
+ that the effective granularity of the limits might influence their enforcement. For example, time limits
+ specified for <varname>LimitCPU=</varname> will be rounded up implicitly to multiples of 1s. For
+ <varname>LimitNICE=</varname> the value may be specified in two syntaxes: if prefixed with <literal>+</literal>
+ or <literal>-</literal>, the value is understood as regular Linux nice value in the range -20..19. If not
+ prefixed like this the value is understood as raw resource limit parameter in the range 0..40 (with 0 being
+ equivalent to 1).</para>
<para>Note that most process resource limits configured with
these options are per-process, and processes may fork in order
diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml
index 2d6339680b..dc3fee5dfb 100644
--- a/man/systemd.socket.xml
+++ b/man/systemd.socket.xml
@@ -807,6 +807,22 @@
suffix.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>TriggerLimitIntervalSec=</varname></term>
+ <term><varname>TriggerLimitIntervalBurst=</varname></term>
+
+ <listitem><para>Configures a limit on how often this socket unit my be activated within a specific time
+ interval. The <varname>TriggerLimitIntervalSec=</varname> may be used to configure the length of the time
+ interval in the usual time units <literal>us</literal>, <literal>ms</literal>, <literal>s</literal>,
+ <literal>min</literal>, <literal>h</literal>, … and defaults to 5s (See
+ <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry> for details on
+ the various time units available). The <varname>TriggerLimitBurst=</varname> setting takes an integer value and
+ specifies the numer of permitted activations per time interval, and defaults to 2500 (thus by default
+ permitting 2500 activations per 5s). Set either to 0 to disable any form of trigger rate limiting. If the limit
+ is hit, the socket unit is placed into a failure mode, and will not be connectible anymore until
+ restarted. Note that this limit is enforced before the service activation is enqueued.</para></listitem>
+ </varlistentry>
+
</variablelist>
<para>Check
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 7993301167..f4b13a7a77 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -751,14 +751,14 @@
</varlistentry>
<varlistentry>
- <term><varname>StartLimitInterval=</varname></term>
+ <term><varname>StartLimitIntervalSec=</varname></term>
<term><varname>StartLimitBurst=</varname></term>
<listitem><para>Configure unit start rate limiting. By default, units which are started more than 5 times
within 10 seconds are not permitted to start any more times until the 10 second interval ends. With these two
- options, this rate limiting may be modified. Use <varname>StartLimitInterval=</varname> to configure the
- checking interval (defaults to <varname>DefaultStartLimitInterval=</varname> in manager configuration file, set
- to 0 to disable any kind of rate limiting). Use <varname>StartLimitBurst=</varname> to configure how many
+ options, this rate limiting may be modified. Use <varname>StartLimitIntervalSec=</varname> to configure the
+ checking interval (defaults to <varname>DefaultStartLimitIntervalSec=</varname> in manager configuration file,
+ set to 0 to disable any kind of rate limiting). Use <varname>StartLimitBurst=</varname> to configure how many
starts per interval are allowed (defaults to <varname>DefaultStartLimitBurst=</varname> in manager
configuration file). These configuration options are particularly useful in conjunction with the service
setting <varname>Restart=</varname> (see
@@ -769,14 +769,15 @@
manually at a later point, from which point on, the restart logic is again activated. Note that
<command>systemctl reset-failed</command> will cause the restart rate counter for a service to be flushed,
which is useful if the administrator wants to manually start a unit and the start limit interferes with
- that.</para></listitem>
+ that. Note that this rate-limiting is enforced after any unit condition checks are executed, and hence unit
+ activations with failing conditions are not counted by this rate limiting.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>StartLimitAction=</varname></term>
<listitem><para>Configure the action to take if the rate limit configured with
- <varname>StartLimitInterval=</varname> and <varname>StartLimitBurst=</varname> is hit. Takes one of
+ <varname>StartLimitIntervalSec=</varname> and <varname>StartLimitBurst=</varname> is hit. Takes one of
<option>none</option>, <option>reboot</option>, <option>reboot-force</option>,
<option>reboot-immediate</option>, <option>poweroff</option>, <option>poweroff-force</option> or
<option>poweroff-immediate</option>. If <option>none</option> is set, hitting the rate limit will trigger no
diff --git a/src/basic/missing.h b/src/basic/missing.h
index b389e94cf7..22ea8f67cc 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -557,7 +557,7 @@ struct btrfs_ioctl_quota_ctl_args {
#define IFLA_INET6_ADDR_GEN_MODE 8
#define __IFLA_INET6_MAX 9
-#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
+#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
#define IN6_ADDR_GEN_MODE_EUI64 0
#define IN6_ADDR_GEN_MODE_NONE 1
@@ -742,7 +742,7 @@ struct btrfs_ioctl_quota_ctl_args {
#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
#endif
-#if !HAVE_DECL_IFLA_BR_PRIORITY
+#if !HAVE_DECL_IFLA_BR_VLAN_DEFAULT_PVID
#define IFLA_BR_UNSPEC 0
#define IFLA_BR_FORWARD_DELAY 1
#define IFLA_BR_HELLO_TIME 2
diff --git a/src/basic/rlimit-util.c b/src/basic/rlimit-util.c
index 7540b43215..ee063720ed 100644
--- a/src/basic/rlimit-util.c
+++ b/src/basic/rlimit-util.c
@@ -153,6 +153,56 @@ static int rlimit_parse_usec(const char *val, rlim_t *ret) {
return 0;
}
+static int rlimit_parse_nice(const char *val, rlim_t *ret) {
+ uint64_t rl;
+ int r;
+
+ /* So, Linux is weird. The range for RLIMIT_NICE is 40..1, mapping to the nice levels -20..19. However, the
+ * RLIMIT_NICE limit defaults to 0 by the kernel, i.e. a value that maps to nice level 20, which of course is
+ * bogus and does not exist. In order to permit parsing the RLIMIT_NICE of 0 here we hence implement a slight
+ * asymmetry: when parsing as positive nice level we permit 0..19. When parsing as negative nice level, we
+ * permit -20..0. But when parsing as raw resource limit value then we also allow the special value 0.
+ *
+ * Yeah, Linux is quality engineering sometimes... */
+
+ if (val[0] == '+') {
+
+ /* Prefixed with "+": Parse as positive user-friendly nice value */
+ r = safe_atou64(val + 1, &rl);
+ if (r < 0)
+ return r;
+
+ if (rl >= PRIO_MAX)
+ return -ERANGE;
+
+ rl = 20 - rl;
+
+ } else if (val[0] == '-') {
+
+ /* Prefixed with "-": Parse as negative user-friendly nice value */
+ r = safe_atou64(val + 1, &rl);
+ if (r < 0)
+ return r;
+
+ if (rl > (uint64_t) (-PRIO_MIN))
+ return -ERANGE;
+
+ rl = 20 + rl;
+ } else {
+
+ /* Not prefixed: parse as raw resource limit value */
+ r = safe_atou64(val, &rl);
+ if (r < 0)
+ return r;
+
+ if (rl > (uint64_t) (20 - PRIO_MIN))
+ return -ERANGE;
+ }
+
+ *ret = (rlim_t) rl;
+ return 0;
+}
+
static int (*const rlimit_parse_table[_RLIMIT_MAX])(const char *val, rlim_t *ret) = {
[RLIMIT_CPU] = rlimit_parse_sec,
[RLIMIT_FSIZE] = rlimit_parse_size,
@@ -167,7 +217,7 @@ static int (*const rlimit_parse_table[_RLIMIT_MAX])(const char *val, rlim_t *ret
[RLIMIT_LOCKS] = rlimit_parse_u64,
[RLIMIT_SIGPENDING] = rlimit_parse_u64,
[RLIMIT_MSGQUEUE] = rlimit_parse_size,
- [RLIMIT_NICE] = rlimit_parse_u64,
+ [RLIMIT_NICE] = rlimit_parse_nice,
[RLIMIT_RTPRIO] = rlimit_parse_u64,
[RLIMIT_RTTIME] = rlimit_parse_usec,
};
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 73c50766d1..d45f511489 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -2050,7 +2050,8 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_PROPERTY("DefaultTimeoutStartUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultTimeoutStopUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultRestartUSec", "t", bus_property_get_usec, offsetof(Manager, default_restart_usec), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("DefaultStartLimitInterval", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultStartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DefaultStartLimitInterval", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), /* obsolete alias name */
SD_BUS_PROPERTY("DefaultStartLimitBurst", "u", bus_property_get_unsigned, offsetof(Manager, default_start_limit_burst), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultCPUAccounting", "b", bus_property_get_bool, offsetof(Manager, default_cpu_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultBlockIOAccounting", "b", bus_property_get_bool, offsetof(Manager, default_blockio_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
index d33e494f6b..bb09a515f8 100644
--- a/src/core/dbus-socket.c
+++ b/src/core/dbus-socket.c
@@ -149,6 +149,8 @@ const sd_bus_vtable bus_socket_vtable[] = {
SD_BUS_PROPERTY("NAccepted", "u", bus_property_get_unsigned, offsetof(Socket, n_accepted), 0),
SD_BUS_PROPERTY("FileDescriptorName", "s", property_get_fdname, 0, 0),
SD_BUS_PROPERTY("SocketProtocol", "i", bus_property_get_int, offsetof(Socket, socket_protocol), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("TriggerLimitIntervalSec", "t", bus_property_get_usec, offsetof(Socket, trigger_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("TriggerLimitBurst", "u", bus_property_get_unsigned, offsetof(Socket, trigger_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPre", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index abe30413c3..e912fe2192 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -704,7 +704,8 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0),
SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), /* obsolete alias name */
SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 5568b4696f..928b913c7b 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -164,6 +164,8 @@ Unit.IgnoreOnSnapshot, config_parse_warn_compat, DISABLED_LE
Unit.JobTimeoutSec, config_parse_sec_fix_0, 0, offsetof(Unit, job_timeout)
Unit.JobTimeoutAction, config_parse_failure_action, 0, offsetof(Unit, job_timeout_action)
Unit.JobTimeoutRebootArgument, config_parse_string, 0, offsetof(Unit, job_timeout_reboot_arg)
+Unit.StartLimitIntervalSec, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
+m4_dnl The following is a legacy alias name for compatibility
Unit.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
Unit.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst)
Unit.StartLimitAction, config_parse_failure_action, 0, offsetof(Unit, start_limit_action)
@@ -220,6 +222,7 @@ Service.TimeoutStartSec, config_parse_service_timeout, 0,
Service.TimeoutStopSec, config_parse_service_timeout, 0, 0
Service.RuntimeMaxSec, config_parse_sec, 0, offsetof(Service, runtime_max_usec)
Service.WatchdogSec, config_parse_sec, 0, offsetof(Service, watchdog_usec)
+m4_dnl The following three only exist for compatibility, they moved into Unit, see above
Service.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst)
Service.StartLimitAction, config_parse_failure_action, 0, offsetof(Unit, start_limit_action)
@@ -297,6 +300,8 @@ Socket.RemoveOnStop, config_parse_bool, 0,
Socket.Symlinks, config_parse_unit_path_strv_printf, 0, offsetof(Socket, symlinks)
Socket.FileDescriptorName, config_parse_fdname, 0, 0
Socket.Service, config_parse_socket_service, 0, 0
+Socket.TriggerLimitIntervalSec, config_parse_sec, 0, offsetof(Socket, trigger_limit.interval)
+Socket.TriggerLimitBurst, config_parse_unsigned, 0, offsetof(Socket, trigger_limit.burst)
m4_ifdef(`HAVE_SMACK',
`Socket.SmackLabel, config_parse_string, 0, offsetof(Socket, smack)
Socket.SmackLabelIPIn, config_parse_string, 0, offsetof(Socket, smack_ip_in)
diff --git a/src/core/main.c b/src/core/main.c
index 75c5ff81f2..ed4d42c8cc 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -289,6 +289,7 @@ static int parse_crash_chvt(const char *value) {
}
static int set_machine_id(const char *m) {
+ assert(m);
if (sd_id128_from_string(m, &arg_machine_id) < 0)
return -EINVAL;
@@ -669,7 +670,8 @@ static int parse_config_file(void) {
{ "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_default_timeout_start_usec },
{ "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_default_timeout_stop_usec },
{ "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_default_restart_usec },
- { "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval },
+ { "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval }, /* obsolete alias */
+ { "Manager", "DefaultStartLimitIntervalSec",config_parse_sec, 0, &arg_default_start_limit_interval },
{ "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst },
{ "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
{ "Manager", "DefaultLimitCPU", config_parse_limit, RLIMIT_CPU, arg_default_rlimit },
diff --git a/src/core/service.c b/src/core/service.c
index b46dd8bcdd..f7a3fcf2b9 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -180,20 +180,17 @@ static int service_set_main_pid(Service *s, pid_t pid) {
return 0;
}
-static void service_close_socket_fd(Service *s) {
+void service_close_socket_fd(Service *s) {
assert(s);
- s->socket_fd = asynchronous_close(s->socket_fd);
-}
-
-static void service_connection_unref(Service *s) {
- assert(s);
+ /* Undo the effect of service_set_socket_fd(). */
- if (!UNIT_ISSET(s->accept_socket))
- return;
+ s->socket_fd = asynchronous_close(s->socket_fd);
- socket_connection_unref(SOCKET(UNIT_DEREF(s->accept_socket)));
- unit_ref_unset(&s->accept_socket);
+ if (UNIT_ISSET(s->accept_socket)) {
+ socket_connection_unref(SOCKET(UNIT_DEREF(s->accept_socket)));
+ unit_ref_unset(&s->accept_socket);
+ }
}
static void service_stop_watchdog(Service *s) {
@@ -321,7 +318,6 @@ static void service_done(Unit *u) {
s->bus_name_owner = mfree(s->bus_name_owner);
service_close_socket_fd(s);
- service_connection_unref(s);
unit_ref_unset(&s->accept_socket);
@@ -910,10 +906,8 @@ static void service_set_state(Service *s, ServiceState state) {
SERVICE_RUNNING, SERVICE_RELOAD,
SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL) &&
- !(state == SERVICE_DEAD && UNIT(s)->job)) {
+ !(state == SERVICE_DEAD && UNIT(s)->job))
service_close_socket_fd(s);
- service_connection_unref(s);
- }
if (!IN_SET(state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD))
service_stop_watchdog(s);
@@ -3139,9 +3133,8 @@ int service_set_socket_fd(Service *s, int fd, Socket *sock, bool selinux_context
assert(s);
assert(fd >= 0);
- /* This is called by the socket code when instantiating a new
- * service for a stream socket and the socket needs to be
- * configured. */
+ /* This is called by the socket code when instantiating a new service for a stream socket and the socket needs
+ * to be configured. We take ownership of the passed fd on success. */
if (UNIT(s)->load_state != UNIT_LOADED)
return -EINVAL;
@@ -3169,12 +3162,15 @@ int service_set_socket_fd(Service *s, int fd, Socket *sock, bool selinux_context
return r;
}
+ r = unit_add_two_dependencies(UNIT(sock), UNIT_BEFORE, UNIT_TRIGGERS, UNIT(s), false);
+ if (r < 0)
+ return r;
+
s->socket_fd = fd;
s->socket_fd_selinux_context_net = selinux_context_net;
unit_ref_set(&s->accept_socket, UNIT(sock));
-
- return unit_add_two_dependencies(UNIT(sock), UNIT_BEFORE, UNIT_TRIGGERS, UNIT(s), false);
+ return 0;
}
static void service_reset_failed(Unit *u) {
diff --git a/src/core/service.h b/src/core/service.h
index cd9e41646e..c7f1e81bdb 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -198,6 +198,7 @@ struct Service {
extern const UnitVTable service_vtable;
int service_set_socket_fd(Service *s, int fd, struct Socket *socket, bool selinux_context_net);
+void service_close_socket_fd(Service *s);
const char* service_restart_to_string(ServiceRestart i) _const_;
ServiceRestart service_restart_from_string(const char *s) _pure_;
diff --git a/src/core/socket.c b/src/core/socket.c
index a9fff9c259..7eeed068bd 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -99,6 +99,8 @@ static void socket_init(Unit *u) {
s->exec_context.std_error = u->manager->default_std_error;
s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
+
+ RATELIMIT_INIT(s->trigger_limit, 5*USEC_PER_SEC, 2500);
}
static void socket_unwatch_control_pid(Socket *s) {
@@ -227,7 +229,6 @@ int socket_instantiate_service(Socket *s) {
if (r < 0)
return r;
- u->no_gc = true;
unit_ref_set(&s->service, u);
return unit_add_two_dependencies(UNIT(s), UNIT_BEFORE, UNIT_TRIGGERS, u, false);
@@ -792,47 +793,45 @@ static void socket_close_fds(Socket *s) {
assert(s);
LIST_FOREACH(port, p, s->ports) {
+ bool was_open;
- p->event_source = sd_event_source_unref(p->event_source);
-
- if (p->fd < 0)
- continue;
+ was_open = p->fd >= 0;
+ p->event_source = sd_event_source_unref(p->event_source);
p->fd = safe_close(p->fd);
socket_cleanup_fd_list(p);
- /* One little note: we should normally not delete any
- * sockets in the file system here! After all some
- * other process we spawned might still have a
- * reference of this fd and wants to continue to use
- * it. Therefore we delete sockets in the file system
- * before we create a new one, not after we stopped
- * using one! */
+ /* One little note: we should normally not delete any sockets in the file system here! After all some
+ * other process we spawned might still have a reference of this fd and wants to continue to use
+ * it. Therefore we normally delete sockets in the file system before we create a new one, not after we
+ * stopped using one! That all said, if the user explicitly requested this, we'll delete them here
+ * anyway, but only then. */
- if (s->remove_on_stop) {
- switch (p->type) {
+ if (!was_open || !s->remove_on_stop)
+ continue;
- case SOCKET_FIFO:
- unlink(p->path);
- break;
+ switch (p->type) {
- case SOCKET_MQUEUE:
- mq_unlink(p->path);
- break;
+ case SOCKET_FIFO:
+ (void) unlink(p->path);
+ break;
- case SOCKET_SOCKET:
- socket_address_unlink(&p->address);
- break;
+ case SOCKET_MQUEUE:
+ (void) mq_unlink(p->path);
+ break;
- default:
- break;
- }
+ case SOCKET_SOCKET:
+ (void) socket_address_unlink(&p->address);
+ break;
+
+ default:
+ break;
}
}
if (s->remove_on_stop)
STRV_FOREACH(i, s->symlinks)
- unlink(*i);
+ (void) unlink(*i);
}
static void socket_apply_socket_options(Socket *s, int fd) {
@@ -1887,6 +1886,9 @@ static void socket_enter_running(Socket *s, int cfd) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
+ /* Note that this call takes possession of the connection fd passed. It either has to assign it somewhere or
+ * close it. */
+
assert(s);
/* We don't take connections anymore if we are supposed to
@@ -1896,7 +1898,7 @@ static void socket_enter_running(Socket *s, int cfd) {
log_unit_debug(UNIT(s), "Suppressing connection request since unit stop is scheduled.");
if (cfd >= 0)
- safe_close(cfd);
+ cfd = safe_close(cfd);
else {
/* Flush all sockets by closing and reopening them */
socket_close_fds(s);
@@ -1918,6 +1920,13 @@ static void socket_enter_running(Socket *s, int cfd) {
return;
}
+ if (!ratelimit_test(&s->trigger_limit)) {
+ safe_close(cfd);
+ log_unit_warning(UNIT(s), "Trigger limit hit, refusing further activation.");
+ socket_enter_stop_pre(s, SOCKET_FAILURE_TRIGGER_LIMIT_HIT);
+ return;
+ }
+
if (cfd < 0) {
Iterator i;
Unit *other;
@@ -1949,7 +1958,7 @@ static void socket_enter_running(Socket *s, int cfd) {
Service *service;
if (s->n_connections >= s->max_connections) {
- log_unit_warning(UNIT(s), "Too many incoming connections (%u)", s->n_connections);
+ log_unit_warning(UNIT(s), "Too many incoming connections (%u), refusing connection attempt.", s->n_connections);
safe_close(cfd);
return;
}
@@ -1965,6 +1974,7 @@ static void socket_enter_running(Socket *s, int cfd) {
/* ENOTCONN is legitimate if TCP RST was received.
* This connection is over, but the socket unit lives on. */
+ log_unit_debug(UNIT(s), "Got ENOTCONN on incoming socket, assuming aborted connection attempt, ignoring.");
safe_close(cfd);
return;
}
@@ -1983,22 +1993,24 @@ static void socket_enter_running(Socket *s, int cfd) {
service = SERVICE(UNIT_DEREF(s->service));
unit_ref_unset(&s->service);
- s->n_accepted++;
-
- UNIT(service)->no_gc = false;
+ s->n_accepted++;
unit_choose_id(UNIT(service), name);
r = service_set_socket_fd(service, cfd, s, s->selinux_context_from_net);
if (r < 0)
goto fail;
- cfd = -1;
+ cfd = -1; /* We passed ownership of the fd to the service now. Forget it here. */
s->n_connections++;
r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, &error, NULL);
- if (r < 0)
+ if (r < 0) {
+ /* We failed to activate the new service, but it still exists. Let's make sure the service
+ * closes and forgets the connection fd again, immediately. */
+ service_close_socket_fd(service);
goto fail;
+ }
/* Notify clients about changed counters */
unit_add_to_dbus_queue(UNIT(s));
@@ -2806,6 +2818,7 @@ static const char* const socket_result_table[_SOCKET_RESULT_MAX] = {
[SOCKET_FAILURE_EXIT_CODE] = "exit-code",
[SOCKET_FAILURE_SIGNAL] = "signal",
[SOCKET_FAILURE_CORE_DUMP] = "core-dump",
+ [SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
[SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit"
};
diff --git a/src/core/socket.h b/src/core/socket.h
index b537b026a7..2a4b1bb674 100644
--- a/src/core/socket.h
+++ b/src/core/socket.h
@@ -52,6 +52,7 @@ typedef enum SocketResult {
SOCKET_FAILURE_EXIT_CODE,
SOCKET_FAILURE_SIGNAL,
SOCKET_FAILURE_CORE_DUMP,
+ SOCKET_FAILURE_TRIGGER_LIMIT_HIT,
SOCKET_FAILURE_SERVICE_START_LIMIT_HIT,
_SOCKET_RESULT_MAX,
_SOCKET_RESULT_INVALID = -1
@@ -156,6 +157,8 @@ struct Socket {
bool reset_cpu_usage:1;
char *fdname;
+
+ RateLimit trigger_limit;
};
/* Called from the service code when collecting fds */
diff --git a/src/core/system.conf b/src/core/system.conf
index e2ded27333..eacd7ee282 100644
--- a/src/core/system.conf
+++ b/src/core/system.conf
@@ -34,7 +34,7 @@
#DefaultTimeoutStartSec=90s
#DefaultTimeoutStopSec=90s
#DefaultRestartSec=100ms
-#DefaultStartLimitInterval=10s
+#DefaultStartLimitIntervalSec=10s
#DefaultStartLimitBurst=5
#DefaultEnvironment=
#DefaultCPUAccounting=no
diff --git a/src/core/unit.c b/src/core/unit.c
index cb79c7c6b1..81cd7ee2b8 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1497,11 +1497,6 @@ int unit_start(Unit *u) {
if (UNIT_IS_ACTIVE_OR_RELOADING(state))
return -EALREADY;
- /* Make sure we don't enter a busy loop of some kind. */
- r = unit_start_limit_test(u);
- if (r < 0)
- return r;
-
/* Units that aren't loaded cannot be started */
if (u->load_state != UNIT_LOADED)
return -EINVAL;
@@ -1543,6 +1538,11 @@ int unit_start(Unit *u) {
if (!UNIT_VTABLE(u)->start)
return -EBADR;
+ /* Make sure we don't enter a busy loop of some kind. */
+ r = unit_start_limit_test(u);
+ if (r < 0)
+ return r;
+
/* We don't suppress calls to ->start() here when we are
* already starting, to allow this request to be used as a
* "hurry up" call, for example when the unit is in some "auto
@@ -3222,6 +3222,10 @@ void unit_ref_unset(UnitRef *ref) {
if (!ref->unit)
return;
+ /* We are about to drop a reference to the unit, make sure the garbage collection has a look at it as it might
+ * be unreferenced now. */
+ unit_add_to_gc_queue(ref->unit);
+
LIST_REMOVE(refs, ref->unit->refs, ref);
ref->unit = NULL;
}
diff --git a/src/core/user.conf b/src/core/user.conf
index 87c8164378..b427f1ef6d 100644
--- a/src/core/user.conf
+++ b/src/core/user.conf
@@ -23,7 +23,7 @@
#DefaultTimeoutStartSec=90s
#DefaultTimeoutStopSec=90s
#DefaultRestartSec=100ms
-#DefaultStartLimitInterval=10s
+#DefaultStartLimitIntervalSec=10s
#DefaultStartLimitBurst=5
#DefaultEnvironment=
#DefaultLimitCPU=
diff --git a/src/journal/journald-gperf.gperf b/src/journal/journald-gperf.gperf
index c154610c54..7fecd7a964 100644
--- a/src/journal/journald-gperf.gperf
+++ b/src/journal/journald-gperf.gperf
@@ -19,7 +19,9 @@ Journal.Storage, config_parse_storage, 0, offsetof(Server, storage
Journal.Compress, config_parse_bool, 0, offsetof(Server, compress)
Journal.Seal, config_parse_bool, 0, offsetof(Server, seal)
Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(Server, sync_interval_usec)
+# The following is a legacy name for compatibility
Journal.RateLimitInterval, config_parse_sec, 0, offsetof(Server, rate_limit_interval)
+Journal.RateLimitIntervalSec,config_parse_sec, 0, offsetof(Server, rate_limit_interval)
Journal.RateLimitBurst, config_parse_unsigned, 0, offsetof(Server, rate_limit_burst)
Journal.SystemMaxUse, config_parse_iec_uint64, 0, offsetof(Server, system_metrics.max_use)
Journal.SystemMaxFileSize, config_parse_iec_uint64, 0, offsetof(Server, system_metrics.max_size)
diff --git a/src/journal/journald.conf b/src/journal/journald.conf
index 7beb96c671..2541b949be 100644
--- a/src/journal/journald.conf
+++ b/src/journal/journald.conf
@@ -17,7 +17,7 @@
#Seal=yes
#SplitMode=uid
#SyncIntervalSec=5m
-#RateLimitInterval=30s
+#RateLimitIntervalSec=30s
#RateLimitBurst=1000
#SystemMaxUse=
#SystemKeepFree=
diff --git a/src/test/test-rlimit-util.c b/src/test/test-rlimit-util.c
index d9ac9368cd..62afd2de5e 100644
--- a/src/test/test-rlimit-util.c
+++ b/src/test/test-rlimit-util.c
@@ -99,6 +99,18 @@ int main(int argc, char *argv[]) {
test_rlimit_parse_format(RLIMIT_NOFILE, "", 0, 0, -EINVAL, NULL);
test_rlimit_parse_format(RLIMIT_NOFILE, "5:4", 0, 0, -EILSEQ, NULL);
test_rlimit_parse_format(RLIMIT_NOFILE, "5:4:3", 0, 0, -EINVAL, NULL);
+ test_rlimit_parse_format(RLIMIT_NICE, "20", 20, 20, 0, "20");
+ test_rlimit_parse_format(RLIMIT_NICE, "40", 40, 40, 0, "40");
+ test_rlimit_parse_format(RLIMIT_NICE, "41", 41, 41, -ERANGE, "41");
+ test_rlimit_parse_format(RLIMIT_NICE, "0", 0, 0, 0, "0");
+ test_rlimit_parse_format(RLIMIT_NICE, "-7", 27, 27, 0, "27");
+ test_rlimit_parse_format(RLIMIT_NICE, "-20", 40, 40, 0, "40");
+ test_rlimit_parse_format(RLIMIT_NICE, "-21", 41, 41, -ERANGE, "41");
+ test_rlimit_parse_format(RLIMIT_NICE, "-0", 20, 20, 0, "20");
+ test_rlimit_parse_format(RLIMIT_NICE, "+7", 13, 13, 0, "13");
+ test_rlimit_parse_format(RLIMIT_NICE, "+19", 1, 1, 0, "1");
+ test_rlimit_parse_format(RLIMIT_NICE, "+20", 0, 0, -ERANGE, "0");
+ test_rlimit_parse_format(RLIMIT_NICE, "+0", 20, 20, 0, "20");
return 0;
}