Note: This bug is displayed in read-only format because the product is no longer active in Red Hat Bugzilla.
RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.

Bug 2011459

Summary: Tuned performs a full rollback when it hangs at shutdown
Product: Red Hat Enterprise Linux 8 Reporter: Frank Hirtz <fhirtz>
Component: tunedAssignee: Jaroslav Škarvada <jskarvad>
Status: CLOSED ERRATA QA Contact: Robin Hack <rhack>
Severity: medium Docs Contact:
Priority: unspecified    
Version: 8.0CC: jeder, jskarvad, jzerdik
Target Milestone: rcKeywords: Patch, TestCaseNeeded, Triaged, Upstream
Target Release: ---Flags: pm-rhel: mirror+
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: tuned-2.18.0-0.1.rc1.el8 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2022-05-10 15:31:16 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Frank Hirtz 2021-10-06 16:01:38 UTC
Description of problem:
Tuned performs a full rollback when it hangs at shutdown

We have profiles modeled against cpu-partitioning, extended to configure cpusets (using the cgconfig service) and isolate the system early at boot using cgroups rather than using isolcpus.
 
Two of our hosts lost all their setting after a week-end reboot. What seemed to happen is that tuned hung during shutdown, and eventually systemd killed it (after exactly 50 seconds). We suspect that upon receiving the SIGTERM tuned performed a full rollback instead of merely dying without undoing non-persistent tuning. Here’s the relevant portion of the tuned log:
 
2021-07-10 22:28:53,554 INFO     tuned.plugins.plugin_bootloader: removing directory '/tmp/tmp.jPMqr1omNZ'
2021-07-10 22:28:53,632 INFO     tuned.daemon.daemon: static tuning from profile 'ms-lc' applied
2021-07-17 22:10:08,675 INFO     tuned.daemon.controller: terminating controller
2021-07-17 22:10:08,676 INFO     tuned.daemon.daemon: stopping tuning
2021-07-17 22:10:58,798 INFO     tuned.daemon.daemon: terminating Tuned, rolling back all changes
2021-07-17 22:10:58,798 INFO     tuned.plugins.plugin_bootloader: removing grub2 tuning previously added by Tuned
2021-07-17 22:10:58,800 INFO     tuned.plugins.plugin_bootloader: removing initrd image '/boot/tuned-initrd.img'
2021-07-17 22:10:58,821 INFO     tuned.plugins.plugin_script: calling script '/usr/lib/tuned/ms-lc/script.sh' with arguments '['stop', 'full_rollback']'
2021-07-17 22:11:23,991 ERROR    tuned.plugins.plugin_script: script '/usr/lib/tuned/ms-lc/script.sh' error output: 'Failed to execute operation: Connection timed out'
2021-07-17 22:11:24,056 INFO     tuned.plugins.plugin_systemd: removing 'CPUAffinity' systemd tuning previously added by Tuned
2021-07-17 22:11:24,057 CONSOLE  tuned.plugins.plugin_systemd: you may need to manualy run 'dracut -f' to update the systemd configuration in initrd image
2021-07-17 22:11:24,063 INFO     tuned.plugins.plugin_cpu: energy_perf_bias successfully set to 'normal' on cpu 'cpu14'
[...]
 
To me it’s clear that in case of a crash/unclean shutdown tuned should not do more than it do on a normal shutdown, and there is no reason for doing a full rollback.

I understand it’s normal for tuned to undo tunings on shutdown, but there are persistent tunings (ex kernel command-line) that just cannot, else you would never have them active when the host boot up, and for that reason there is a concept of “full rollback” that is only executed on profile changes. So when I restart a host those aren’t undone by design too.

The issue appears to be if for some reason tuned hangs on shutdown, and gets SIGTERM’ed by systemctl, it perform a full rollback.

So only in some cases of unclean shutdown tuned will undo the changes that are needed on the next reboot. Also I’m worried the SIGKILL could prevent rollback during profile switch (we write the active_profile file and restart tuned, and were told that it’s a supported way of setting the tuned profile…)


<snip>

I've been having a deeper look at how tuned works and think that my initial suspicion was incorrect and focusing on the script isn't likely going to go anywhere. That said, the error that the rollback is throwing when trying to do so with the script is interesting to me:  'Failed to execute operation: Connection timed out'. I've seen this before in other contexts and it looks like a systemd/DBus error to me and could be suggesting that there's an issue somewhere in the area. Normally a shutdown won't trigger a rollback and doesn't; there are a few things that we check to decide what the shutdown conditions are and whether a rollback is called for:


<snip>
        # if terminating due to profile switch
        if self._terminate_profile_switch.is_set():
            full_rollback = True
        else: 
            # with systemd it detects system shutdown and in such case it doesn't perform
            # full cleanup, if not shutting down it means that Tuned was explicitly
            # stopped by user and in such case do full cleanup, without systemd never
            # do full cleanup
            full_rollback = False
            if self._full_rollback_required():
                if self._daemon:
                    log.info("terminating Tuned, rolling back all changes")
                    full_rollback = True
...
    def _full_rollback_required(self):
        retcode, out = self._cmd.execute(["systemctl", "is-system-running"], no_errors = [0])
        if retcode < 0:
            return False
        if out[:8] == "stopping":
            return False
        retcode, out = self._cmd.execute(["systemctl", "list-jobs"], no_errors = [0])
        return re.search(r"\b(shutdown|reboot|halt|poweroff).target.*start", out) is None
</snip>


Now this is why the "interesting" message above is so to me. If there's something going on with systemd/dbus around this time and our "systemctl" calls in the daemon to decide whether we need to rollback or not don't work correctly then this could go awry. So, it could be a dbus/systemd issue and this is all fallout. I'm not certain on this, but it's plausible. I'm seeing how we could debug this as I've been unable to reproduce thus far, but need to look further.

<snip>

we've modified tuned to capture the extract RC and output of the failing commands, then we were able to reproduce the issue by faking the systemctl commands output.


There are two commands tuned may run in the _full_rollback_required method... The first is systemctl is-system-running:


Returns false if retcode < 0 or output is stopping. Observation shown that this command normally returns 0 or 1 with output stopping during a normal shutdown, else running or degraded. I'm not sure about the returncode < 0 case as I couldn't find any documentation on systemctl's returncodes, and on affected systems the command returned a RC of 0 with unknown after a 25 seconds timeout (suspected dbus timeout).


This command never returned anything to STDERR in our tests.


If tuned isn't satisfied with this first command it proceeds with the 2nd command, list-jobs. If tuned gets to that point, it only look at the output for a job matching shutdown, reboot, halt or poweroff.


Again I could not see anything about the expected RC for this command (which isn't used regardless), but on failing systems RC is 1, there is no output to STDOUT and STDERR gets:


Failed to list jobs: Connection timed out
Normally, from my observations this comment should always return something to STDOUT and never to STDERR, so the _full_rollback_required method method should probably return False if the regex doesn't match and there is anything on STDERR or nothing on STDOUT (perhaps check RC if that makes sense, again I could not find any documentation on the expected RC).
</snip>

**note: This was seen on RHEL7, but it doesn't look like this behavior would change on RHEL8 if the read on what's happening is correct so I'm raising it on the newer OS since this would be out of scope on RHEL7 at this phase**

Comment 1 Jaroslav Škarvada 2021-11-02 17:19:48 UTC
Thanks for the analysis of the problem. I think we should extend the check and not do the full rollback in case the 'systemctl list-jobs' command fails, i.e.  do nothing if we don't know what's going there.

Comment 4 Jaroslav Škarvada 2022-02-01 20:58:26 UTC
(In reply to Frank Hirtz from comment #0)
> There are two commands tuned may run in the _full_rollback_required
> method... The first is systemctl is-system-running:
> 
> 
> Returns false if retcode < 0 or output is stopping. Observation shown that
> this command normally returns 0 or 1 with output stopping during a normal
> shutdown, else running or degraded. I'm not sure about the returncode < 0
> case as I couldn't find any documentation on systemctl's returncodes, and on
> affected systems the command returned a RC of 0 with unknown after a 25
> seconds timeout (suspected dbus timeout).

Just FYI TuneD internal API returns -errno retcode in case of command failure, usually the errno is ENOENT on systems without systemd, hence the retcode < 0 check, i.e. not doing full rollback if systemd is not available or non-functional.

Comment 5 Jaroslav Škarvada 2022-02-01 21:03:20 UTC
Upstream PR:
https://github.com/redhat-performance/tuned/pull/407

Comment 17 errata-xmlrpc 2022-05-10 15:31:16 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (tuned bug fix and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2022:2106