commit:     875c8dbcc6e9c98d289ec1869c61fbcc4da5864c
Author:     Florian Schmaus <flow <AT> gentoo <DOT> org>
AuthorDate: Tue Jun 29 08:54:19 2021 +0000
Commit:     Michał Górny <mgorny <AT> gentoo <DOT> org>
CommitDate: Wed Aug 18 16:52:30 2021 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=875c8dbc

pid-ns-init: Consider autogroup scheduling

With Linux's autogroup scheduling feature (CONFIG_SCHED_AUTOGROUP)
setting a nice value on a per-process base has only an effect for
scheduling decisions relative to the other threads in the same
session (typically: the same terminal window). See the section "The
nice value and group scheduling" in the sched(7) man page.

Basically this means that portage "just" setting the nice value, has
no effect in presence of autogroup scheduling being active (which is
probably true for most (desktop) user systems).

This commit changes pid-ns-init to set the autogroup's nice value in
case autogroups are present (detected by the existence of
/proc/self/autogroup).

My initial attempt to consider autogroup scheduling revolved around
nice() in actions.py setting the autogroup nice value and restoring
the original value with an atexit handler. See
055abe523c2c ("PORTAGE_NICENESS: Consider autogroup
scheduling"). However this is fragile if the performing process is
unprivileged (think of a user calling "ebuild foo-1.0.0.ebuild
manifest") as Linux employs a rate limiting to autogroup changes by
unprivileged processes [1].

Eventually this means portage can only reliable set the autogroup
value within the pid-ns-init helper, where a new session is
created. We only set the autogroup value within the new session, which
relieves portage from restoring the original value, as the autogroup
will cease to exist once the session exists, i.e. with the termination
of the pid-ns-init helper.

Note that the pid-ns-init helper is an optional portage feature
'pid-sandbox'. Only if this is enabled, portage will set the
autogroup's nice value.

1: 
https://github.com/torvalds/linux/blob/fd0aa1a4567d0f09e1bfe367a950b004f99ac290/kernel/sched/autogroup.c#L226-L227

Bug: https://bugs.gentoo.org/777492
Signed-off-by: Florian Schmaus <flow <AT> gentoo.org>
Closes: https://github.com/gentoo/portage/pull/728
Signed-off-by: Michał Górny <mgorny <AT> gentoo.org>

 bin/pid-ns-init | 20 +++++++++++++++++++-
 man/make.conf.5 |  5 ++++-
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/bin/pid-ns-init b/bin/pid-ns-init
index e410dd028..1c5125185 100644
--- a/bin/pid-ns-init
+++ b/bin/pid-ns-init
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# Copyright 2018-2020 Gentoo Authors
+# Copyright 2018-2021 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import errno
@@ -12,6 +12,7 @@ import subprocess
 import sys
 import termios
 
+from pathlib import Path
 
 KILL_SIGNALS = (
        signal.SIGINT,
@@ -91,9 +92,26 @@ def main(argv):
                        'preexec_fn': functools.partial(preexec_fn, uid, gid, 
groups, umask),
                        'pass_fds': pass_fds,
                }
+
+               # Obtain the current nice value, which will be potentially be
+               # used as the newly created session's autogroup nice value.
+               nice_value = os.nice(0)
+
                # Isolate parent process from process group SIGSTOP (bug 675870)
                setsid = True
                os.setsid()
+
+               # Set the previously obtained autogroup nice value again,
+               # since we created a new session with os.setsid() above.
+               try:
+                       Path("/proc/self/autogroup").write_text(str(nice_value))
+               except EnvironmentError as e:
+                       # The process is likely not allowed to set the autogroup
+                       # value (Linux employs a rate limiting for unprivileged
+                       # changes to the autogroup value) or autogroups are not
+                       # enabled. Nothing we can do here, so we simply carry 
on.
+                       pass
+
                if sys.stdout.isatty():
                        try:
                                fcntl.ioctl(sys.stdout, termios.TIOCSCTTY, 0)

diff --git a/man/make.conf.5 b/man/make.conf.5
index db742fdb5..0790933f7 100644
--- a/man/make.conf.5
+++ b/man/make.conf.5
@@ -1,4 +1,4 @@
-.TH "MAKE.CONF" "5" "May 2021" "Portage VERSION" "Portage"
+.TH "MAKE.CONF" "5" "Jun 2021" "Portage VERSION" "Portage"
 .SH "NAME"
 make.conf \- custom settings for Portage
 .SH "SYNOPSIS"
@@ -993,6 +993,9 @@ string should contain a \\${PID} place-holder that will be 
substituted
 with an integer pid. For example, a value of "ionice \-c 3 \-p \\${PID}"
 will set idle io priority. For more information about ionice, see
 \fBionice\fR(1). This variable is unset by default.
+.br
+Portage will also set the autogroup-nice value (see fBsched\fR(7))), if
+FEATURES="pid\-sandbox" is enabled.
 .TP
 .B PORTAGE_LOG_FILTER_FILE_CMD
 This variable specifies a command that filters build log output to a

Reply via email to