Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

systemd: Don't open and close tuned DBus connections asynchronously #21114

Merged

Conversation

mvollmer
Copy link
Member

@mvollmer mvollmer commented Oct 14, 2024

The TunedPerformanceProfile component was keeping a DBus connection open to tuned, and was closing and reopening it whenever something might have changed that requires it.

This happened asynchronously with the rest of the code that was using this DBus connection, and would frequently cause that code to fail with "disconnected" errors.

Also, the TunedDialog was itself causing changes that require a new DBus connection (namely starting the tuned.service), but was always working with the one that was originally passed into it via its properties.

Let's straighten this all out:

  • Polling for the button state will open its own dedicated DBUs connection and close it when polling is done. There is no need to keep a DBus connection open for the whole Cockpit session.

  • The tuned.service is started when the dialog is opened and a DBus
    connection is opened explicitly for the dialog after that and
    closed when the dialog is closed.

@mvollmer
Copy link
Member Author

Starting the service might be slow and it would be best to do it inside the dialog, while the spinner is showing. That is probably straightforward.

Also, I think our DBusClient is supposed to survive the dbus service coming and going, maybe with some flags and owner watching. That would be another, even cleaner, way of handling this, by only having a single DBusClient that is never closed and always works.

@mvollmer
Copy link
Member Author

by only having a single DBusClient that is never closed and always works.

(except when superuser.allowed changes)

Copy link
Member

@jelly jelly left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally, the dialog loads a lot faster!

@@ -303,14 +300,14 @@ const TunedDialog = ({
className="ct-m-stretch-body"
isOpen
help={help}
onClose={Dialogs.close}
onClose={() => dialogResult.resolve()}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The equivalent would be dialogResult.resolve

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessarily. The this inside the call is different, and that might matter.

@mvollmer
Copy link
Member Author

Starting the service might be slow and it would be best to do it inside the dialog, while the spinner is showing. That is probably straightforward.

Also, I think our DBusClient is supposed to survive the dbus service coming and going, maybe with some flags and owner watching. That would be another, even cleaner, way of handling this, by only having a single DBusClient that is never closed and always works.

Done in #21115.

@mvollmer
Copy link
Member Author

Tested locally, the dialog loads a lot faster!

This is due to this: https://github.com/cockpit-project/cockpit/pull/21114/files#diff-edcd27aeefd91df68948709cd630aaefbc569ac0674cc54693139880404e17bdR101-R108

@mvollmer mvollmer force-pushed the tuned-straighten-out-dbus-connections branch from ec42cb7 to 50c64f6 Compare October 14, 2024 12:54
@mvollmer mvollmer marked this pull request as ready for review October 14, 2024 16:00
@mvollmer mvollmer requested a review from jelly October 15, 2024 09:04
@mvollmer
Copy link
Member Author

Starting the service might be slow and it would be best to do it inside the dialog, while the spinner is showing. That is probably straightforward.

@jelly, what do you think about this? Should we start tuned.service while the dialog is already open? Then the TunedDialog component needs to maintain its own DBusClient ins a useState hook, probably.

@jelly
Copy link
Member

jelly commented Oct 16, 2024

Starting the service might be slow and it would be best to do it inside the dialog, while the spinner is showing. That is probably straightforward.

@jelly, what do you think about this? Should we start tuned.service while the dialog is already open? Then the TunedDialog component needs to maintain its own DBusClient ins a useState hook, probably.

Hmmm right, what if it fails the error message get's "lost", so maybe we should do the extra work (and right thing) And start the service in the dialog?

@mvollmer mvollmer force-pushed the tuned-straighten-out-dbus-connections branch from 50c64f6 to c94b7e5 Compare October 22, 2024 08:32
@mvollmer
Copy link
Member Author

Starting the service might be slow and it would be best to do it inside the dialog, while the spinner is showing. That is probably straightforward.

@jelly, what do you think about this? Should we start tuned.service while the dialog is already open? Then the TunedDialog component needs to maintain its own DBusClient ins a useState hook, probably.

Hmmm right, what if it fails the error message get's "lost", so maybe we should do the extra work (and right thing) And start the service in the dialog?

Yes, catching the error is convincing. I have done this now. The explicit close() function for closing the DBus channel is not great, that should rather be done in a "destroy" function of useObject or useEffect... do we care enough to refactor the code more?

The TunedPerformanceProfile component was keeping a DBus connection
open to tuned, and was closing and reopening it whenever something
might have changed that requires it.

This happened asynchronously with the rest of the code that was using
this DBus connection, and would frequently cause that code to fail
with "disconnected" errors.

Also, the TunedDialog was itself causing changes that require a new
DBus connection (namely starting the tuned.service), but was always
working with the one that was originally passed into it via its
properties.

Let's straighten this all out:

 - Polling for the button state will open its own dedicated DBUs
   connection and close it when polling is done.  There is no need to
   keep a DBus connection open for the whole Cockpit session.

 - The tuned.service is started when the dialog is opened and a DBus
   connection is opened explicitly for the dialog after that and
   closed when the dialog is closed.
@mvollmer mvollmer force-pushed the tuned-straighten-out-dbus-connections branch from c94b7e5 to dad8dd7 Compare October 22, 2024 08:57
@mvollmer
Copy link
Member Author

that should rather be done in a "destroy" function of useObject or useEffect... do we care enough to refactor the code more?

Yes, I did that as well.

@@ -290,9 +290,9 @@ export function proxy(name, kind) {

call_manager(dbus, method, args)
.then(([path]) => { pending_job_path = path })
.catch(() => {
.catch(ex => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

dbus.close();
reject();
reject(ex);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

})
.catch((ex) => {
if (!tunedService.exists)
return ({ state: "not-installed" });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

if (!tunedService.exists)
return ({ state: "not-installed" });
else if (tunedService.state != "running")
return ({ state: "not-running" });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

let status;

if (state == "not-installed")
status = _("Tuned is not available");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

@@ -303,14 +305,14 @@ const TunedDialog = ({
className="ct-m-stretch-body"
isOpen
help={help}
onClose={Dialogs.close}
onClose={() => dialogResult.resolve()}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

title={_("Change performance profile")}
footer={
<>
<Button variant='primary' isDisabled={!selected} onClick={setProfile}>
{_("Change profile")}
</Button>
<Button variant='link' onClick={Dialogs.close}>
<Button variant='link' onClick={() => dialogResult.resolve()}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

@mvollmer mvollmer merged commit e563926 into cockpit-project:main Oct 22, 2024
82 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants