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 emerge to set the autogroup's nice value, instead of the processes' nice value, in case autogroups are present (detected by the existence of /proc/self/autogroup). The tricky part about autogroup nice values is that we want restore the orignal nice value once we are finished. As otherwise, the session, e.g. your terminal, would continue using this value, and so would subsequently executed processes. For that we use Python's atexit functinaly, to register a function that will restore the orignal nice value of the autogroup. Bug: https://bugs.gentoo.org/777492 Signed-off-by: Florian Schmaus <f...@geekplace.eu> --- lib/_emerge/actions.py | 46 +++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/lib/_emerge/actions.py b/lib/_emerge/actions.py index 239bf6f476d1..8f6e7c51b6dc 100644 --- a/lib/_emerge/actions.py +++ b/lib/_emerge/actions.py @@ -1,6 +1,7 @@ # Copyright 1999-2020 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 +import atexit import collections import logging import operator @@ -14,6 +15,7 @@ import textwrap import time import warnings from itertools import chain +from pathlib import Path import portage portage.proxy.lazyimport.lazyimport(globals(), @@ -2632,13 +2634,43 @@ def apply_priorities(settings): nice(settings) def nice(settings): - try: - os.nice(int(settings.get("PORTAGE_NICENESS", "0"))) - except (OSError, ValueError) as e: - out = portage.output.EOutput() - out.eerror("Failed to change nice value to '%s'" % \ - settings.get("PORTAGE_NICENESS", "0")) - out.eerror("%s\n" % str(e)) + autogroup_file = Path("/proc/self/autogroup") + + nice_value : str = settings.get("PORTAGE_NICENESS", "0") + + if not autogroup_file.is_file(): + # Autogroup scheduling is not enabled on this system, + # continue using good ol' os.nice(). + try: + os.nice(int(nice_value)) + except (OSError, ValueError) as e: + out = portage.output.EOutput() + out.eerror("Failed to change nice value to '%s'" % \ + settings.get("PORTAGE_NICENESS", "0")) + out.eerror("%s\n" % str(e)) + return + + with autogroup_file.open('r+') as f: + line = f.readline() + original_autogroup_nice_value = line.split(' ') + + # We need to restore the original nice value of the + # autogroup, as otherwise the session, e.g. the + # terminal where protage was executed in, would + # continue running with that value. + atexit.register( + lambda value: autogroup_file.open('w').write(value), + original_autogroup_nice_value + ) + + try: + f.write(nice_value) + except (OSError) as e: + out = portage.output.EOutput() + out.eerror("Failed to change nice value to '%s'" % \ + settings.get("PORTAGE_NICENESS", "0")) + out.eerror("%s\n" % str(e)) + def ionice(settings): -- 2.26.3