4

I want to reserve a small amount of cpu and memory to be able in case of emergency create tty session and kill a memory hogging X application. cgroups provide this functionality. How do I put all my X applications inside cgroup automatically?

1 Answer 1

4

I use Debian, so the solution is based on systemd cgroup implementation.

The first step is to inspect the cgroups hierarchy:

> systemd-cgls
-.slice
├─user.slice
│ └─user-1000.slice
│   ├─user@1000.service
.....
│   └─session-2.scope
│     ├─1376 lightdm --session-child 14 21
│     ├─1400 x-window-manager
.....

systemd automatically assigns cgroups to terminal sessions. In cgroup hierarchy we need determine which session-*.scope has X applications in it. Default X session scope number is always the same.

To set memory limit to all programs in a scope, type

> systemctl set-property session-2.scope MemoryLimit=14G

This command sets memory limit to the session 2 until reboot.

To make this rule permanent, run

> sudo systemctl edit session-2.scope

in text editor type

[Scope]
MemoryLimit=14G

and save. This rule will persist between reboots. Other resource limits may be set in a same file.


Edit

As derobert pointed out, X session scope number is not guarantied to be the same. More robust solution is to determine this number at runtime.

File /usr/local/bin/resource_limit.sh:

#!/bin/bash

for s in $(systemd-cgls --no-pager --user-unit \
           | grep --extended-regexp --only-matching \
              'session-.{1,3}\.scope');do
    systemctl set-property --runtime "$s" MemoryLimit="$1"
done

File /etc/systemd/system/resource_limit.service:

[Unit]
Description=Limit resources
Requires=multi-user.target
After=multi-user.target

[Service]
Type=oneshot
ExecStartPre=/bin/sleep 5
ExecStart=/usr/local/bin/resource_limit.sh 14G
ExecStop=/usr/local/bin/resource_limit.sh 20G
RemainAfterExit=true

[Install]
WantedBy=graphical.target

Copy files above to your system and issue command

systemctl daemon-reload

After this you may set specified limit (in this case 14G) using command

systemctl start resource_limit.service

and unset it (setting some higher limit value) using command

systemctl stop resource_limit.service

In order to run this script on reboot automatically, issue command

systemctl enable resource_limit.service

Note 1

If your X session does not start fast enough, you may want to increase service delay via ExecStartPre or enable service manually.

Note 2

It is a good idea to also add restrictions to user@1000.service (where 1000 - is a UID) with slightly bigger limit. This way you will always have resources available for system daemons.

2
  • It's just session 2 because they're assigned in order. Here my X session is 4 (also Debian). So you unfortunately can't consistently target the X session by name. You can get a list of sessions from loginctl list-sessions, so I bet it's possible to do it with some scripting.
    – derobert
    Oct 18, 2019 at 20:23
  • @derobert the command loginctl --no-pager --no-legend --property=session list-sessions should do what you desribe, but it looks like the CLI does not respect the --property= part
    – code_monk
    Jul 23, 2020 at 14:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.