]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/units/testsuite-55.sh
e5d930175f7da1fc9a79b11946ea5f7dbf154ec8
[thirdparty/systemd.git] / test / units / testsuite-55.sh
1 #!/usr/bin/env bash
2 # SPDX-License-Identifier: LGPL-2.1-or-later
3 set -eux
4 set -o pipefail
5
6 # shellcheck source=test/units/util.sh
7 . "$(dirname "$0")"/util.sh
8
9 systemd-analyze log-level debug
10
11 # Ensure that the init.scope.d drop-in is applied on boot
12 test "$(cat /sys/fs/cgroup/init.scope/memory.high)" != "max"
13
14 # Loose checks to ensure the environment has the necessary features for systemd-oomd
15 [[ -e /proc/pressure ]] || echo "no PSI" >>/skipped
16 [[ "$(get_cgroup_hierarchy)" == "unified" ]] || echo "no cgroupsv2" >>/skipped
17 [[ -x /usr/lib/systemd/systemd-oomd ]] || echo "no oomd" >>/skipped
18 if [[ -s /skipped ]]; then
19 exit 77
20 fi
21
22 rm -rf /run/systemd/system/testsuite-55-testbloat.service.d
23
24 # Activate swap file if we are in a VM
25 if systemd-detect-virt --vm --quiet; then
26 if [[ "$(findmnt -n -o FSTYPE /)" == btrfs ]]; then
27 btrfs filesystem mkswapfile -s 64M /swapfile
28 else
29 dd if=/dev/zero of=/swapfile bs=1M count=64
30 chmod 0600 /swapfile
31 mkswap /swapfile
32 fi
33
34 swapon /swapfile
35 swapon --show
36 fi
37
38 # Configure oomd explicitly to avoid conflicts with distro dropins
39 mkdir -p /run/systemd/oomd.conf.d/
40 cat >/run/systemd/oomd.conf.d/99-oomd-test.conf <<EOF
41 [OOM]
42 DefaultMemoryPressureDurationSec=2s
43 EOF
44
45 mkdir -p /run/systemd/system/-.slice.d/
46 cat >/run/systemd/system/-.slice.d/99-oomd-test.conf <<EOF
47 [Slice]
48 ManagedOOMSwap=auto
49 EOF
50
51 mkdir -p /run/systemd/system/user@.service.d/
52 cat >/run/systemd/system/user@.service.d/99-oomd-test.conf <<EOF
53 [Service]
54 ManagedOOMMemoryPressure=auto
55 ManagedOOMMemoryPressureLimit=0%
56 EOF
57
58 mkdir -p /run/systemd/system/systemd-oomd.service.d/
59 cat >/run/systemd/system/systemd-oomd.service.d/debug.conf <<EOF
60 [Service]
61 Environment=SYSTEMD_LOG_LEVEL=debug
62 EOF
63
64 systemctl daemon-reload
65
66 # enable the service to ensure dbus-org.freedesktop.oom1.service exists
67 # and D-Bus activation works
68 systemctl enable systemd-oomd.service
69
70 # if oomd is already running for some reasons, then restart it to make sure the above settings to be applied
71 if systemctl is-active systemd-oomd.service; then
72 systemctl restart systemd-oomd.service
73 fi
74
75 if [[ -v ASAN_OPTIONS || -v UBSAN_OPTIONS ]]; then
76 # If we're running with sanitizers, sd-executor might pull in quite a significant chunk of shared
77 # libraries, which in turn causes a lot of pressure that can put us in the front when sd-oomd decides to
78 # go on a killing spree. This fact is exacerbated further on Arch Linux which ships unstripped gcc-libs,
79 # so sd-executor pulls in over 30M of libs on startup. Let's make the MemoryHigh= limit a bit more
80 # generous when running with sanitizers to make the test happy.
81 systemctl edit --runtime --stdin --drop-in=99-MemoryHigh.conf testsuite-55-testchill.service <<EOF
82 [Service]
83 MemoryHigh=60M
84 EOF
85 # Do the same for the user instance as well
86 mkdir -p /run/systemd/user/
87 cp -rfv /run/systemd/system/testsuite-55-testchill.service.d/ /run/systemd/user/
88 else
89 # Ensure that we can start services even with a very low hard memory cap without oom-kills, but skip
90 # under sanitizers as they balloon memory usage.
91 systemd-run -t -p MemoryMax=10M -p MemorySwapMax=0 -p MemoryZSwapMax=0 /bin/true
92 fi
93
94 systemctl start testsuite-55-testchill.service
95 systemctl start testsuite-55-testbloat.service
96
97 # Verify systemd-oomd is monitoring the expected units
98 timeout 1m bash -xec 'until oomctl | grep "/testsuite-55-workload.slice"; do sleep 1; done'
99 oomctl | grep "/testsuite-55-workload.slice"
100 oomctl | grep "20.00%"
101 oomctl | grep "Default Memory Pressure Duration: 2s"
102
103 systemctl status testsuite-55-testchill.service
104
105 # systemd-oomd watches for elevated pressure for 2 seconds before acting.
106 # It can take time to build up pressure so either wait 2 minutes or for the service to fail.
107 for _ in {0..59}; do
108 if ! systemctl status testsuite-55-testbloat.service; then
109 break
110 fi
111 oomctl
112 sleep 2
113 done
114
115 # testbloat should be killed and testchill should be fine
116 if systemctl status testsuite-55-testbloat.service; then exit 42; fi
117 if ! systemctl status testsuite-55-testchill.service; then exit 24; fi
118
119 # Make sure we also work correctly on user units.
120 loginctl enable-linger testuser
121
122 systemctl start --machine "testuser@.host" --user testsuite-55-testchill.service
123 systemctl start --machine "testuser@.host" --user testsuite-55-testbloat.service
124
125 # Verify systemd-oomd is monitoring the expected units
126 # Try to avoid racing the oomctl output check by checking in a loop with a timeout
127 timeout 1m bash -xec 'until oomctl | grep "/testsuite-55-workload.slice"; do sleep 1; done'
128 oomctl | grep -E "/user.slice.*/testsuite-55-workload.slice"
129 oomctl | grep "20.00%"
130 oomctl | grep "Default Memory Pressure Duration: 2s"
131
132 systemctl --machine "testuser@.host" --user status testsuite-55-testchill.service
133
134 # systemd-oomd watches for elevated pressure for 2 seconds before acting.
135 # It can take time to build up pressure so either wait 2 minutes or for the service to fail.
136 for _ in {0..59}; do
137 if ! systemctl --machine "testuser@.host" --user status testsuite-55-testbloat.service; then
138 break
139 fi
140 oomctl
141 sleep 2
142 done
143
144 # testbloat should be killed and testchill should be fine
145 if systemctl --machine "testuser@.host" --user status testsuite-55-testbloat.service; then exit 42; fi
146 if ! systemctl --machine "testuser@.host" --user status testsuite-55-testchill.service; then exit 24; fi
147
148 loginctl disable-linger testuser
149
150 # only run this portion of the test if we can set xattrs
151 if cgroupfs_supports_user_xattrs; then
152 sleep 120 # wait for systemd-oomd kill cool down and elevated memory pressure to come down
153
154 mkdir -p /run/systemd/system/testsuite-55-testbloat.service.d/
155 cat >/run/systemd/system/testsuite-55-testbloat.service.d/override.conf <<EOF
156 [Service]
157 ManagedOOMPreference=avoid
158 EOF
159
160 systemctl daemon-reload
161 systemctl start testsuite-55-testchill.service
162 systemctl start testsuite-55-testmunch.service
163 systemctl start testsuite-55-testbloat.service
164
165 for _ in {0..59}; do
166 if ! systemctl status testsuite-55-testmunch.service; then
167 break
168 fi
169 oomctl
170 sleep 2
171 done
172
173 # testmunch should be killed since testbloat had the avoid xattr on it
174 if ! systemctl status testsuite-55-testbloat.service; then exit 25; fi
175 if systemctl status testsuite-55-testmunch.service; then exit 43; fi
176 if ! systemctl status testsuite-55-testchill.service; then exit 24; fi
177 fi
178
179 systemd-analyze log-level info
180
181 touch /testok