Skip to content

Mark SetBrightness D-Bus calls as no-reply to prevent a reply leak that exhausts the user's bus quota#170

Merged
max-baz merged 2 commits into
max-baz:mainfrom
d3vv3:fix/dbus-reply-leak
Jun 10, 2026
Merged

Mark SetBrightness D-Bus calls as no-reply to prevent a reply leak that exhausts the user's bus quota#170
max-baz merged 2 commits into
max-baz:mainfrom
d3vv3:fix/dbus-reply-leak

Conversation

@d3vv3

@d3vv3 d3vv3 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

On the logind D-Bus brightness path (src/brightness/backlight.rs, used when wluma lacks direct write permission to the sysfs brightness file), wluma sends SetBrightness method calls on a dbus::blocking::Connection but never drains the connectionprocess() / read_write() are never called anywhere in the codebase.

A normal method call expects a reply, so logind returns a method_return for every SetBrightness. Nobody ever reads those replies, so they accumulate without bound in the bus daemon's outgoing queue toward wluma. Because dbus-broker accounts message memory per user, this slowly consumes the user's entire quota. Once it's exhausted, the bus daemon starts disconnecting that user's other clients whenever they request a sizable reply:

dbus-broker: Peer :1.NNNN is being disconnected as it does not have the
resources to receive a reply it requested.

In practice this manifests as unrelated tools breaking — e.g. nm-applet / nmcli reporting "NetworkManager is not running" even though it is, because libnm's GetManagedObjects() reply can no longer be received. Killing wluma (or here, fixing it) immediately frees the quota and the other clients recover. The backed-up socket is directly observable via ss -xp | grep system_bus_socket — wluma's connection shows a large, growing Send-Q.

Fix

SetBrightness has no meaningful return value, so flag the message as no-reply (Message::set_no_reply(true)). logind then never generates a reply and nothing accumulates. Minimal, and keeps the existing fire-and-forget send() model.

(An alternative would be to pump the connection with connection.process(Duration::ZERO) after each send, but suppressing the reply at the source is cleaner and cheaper.)

Testing

  • cargo build succeeds against dbus 0.9.11 (confirms set_no_reply API usage).
  • cargo fmt --check clean.
  • The functional behavior of SetBrightness is unchanged; only the now-unused reply is suppressed.

The logind brightness path sends SetBrightness method calls on a
blocking Connection that is never drained (process()/read_write() are
never called). Each call is a normal method call expecting a reply, so
logind returns a method-return that nobody reads. These replies queue up
in the bus daemon's outgoing buffer to wluma without bound.

Because dbus-broker accounts message memory per user, this slowly
consumes the user's entire quota. Once exhausted, the bus daemon starts
disconnecting that user's other clients when they request any sizable
reply ("...does not have the resources to receive a reply it
requested"), breaking nm-applet, nmcli and similar tools with a
misleading "NetworkManager is not running" even though it is running.

SetBrightness has no meaningful return value, so flag the message as
no-reply. logind then never generates a reply and nothing accumulates.
@max-baz

max-baz commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Thanks! It looks like the default value is already false ( if you follow the chain starting from https://docs.rs/dbus/latest/dbus/message/struct.Message.html#method.Set_no_reply ), do you have some evidence that this PR in fact is not a noop?

@d3vv3

d3vv3 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Hi @max-baz, the no_reply is false by default, meaning a reply is expected. We are changing it to true now, so a reply will not be expected. So it is not a no-op.

@max-baz

max-baz commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Thanks, and apologies! My bad, I started going down the docs and confused myself in the negations 😅 I think the lints are unrelated to your changes, I'll address them later.

@max-baz max-baz merged commit 478ae36 into max-baz:main Jun 10, 2026
1 of 2 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.

2 participants