Skip to content

systemd: fix jitter in dbus connection retry backoff - #85

Merged
AkihiroSuda merged 1 commit into
opencontainers:mainfrom
hakman:systemd-dbus-retry-jitter
Oct 8, 2026
Merged

AkihiroSuda merged 1 commit into
opencontainers:mainfrom
hakman:systemd-dbus-retry-jitter

Conversation

@hakman

@hakman hakman commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

newConnection() retries with exponential backoff when connecting to dbus fails with EAGAIN (#45). The comment says 100ms * 2^attempt + ~12.5% jitter, but the jitter is computed in milliseconds and then converted to time.Duration as is, which makes it nanoseconds:

delay := 100 * time.Millisecond << retry
delay += time.Duration(rand.Int64N(1 + (delay.Milliseconds() >> 3)))

For the first attempt delay.Milliseconds() >> 3 is 12, so the jitter is time.Duration(rand.Int64N(13)), i.e. 0 to 12 nanoseconds. On the last attempt it is at most 800 ns. In effect there is no jitter: clients refused at the same moment retry at the same moment, on every attempt.

This PR makes the jitter 0 to 1/8 of the delay, as the comment intends. rand.N is generic over integer types and takes a time.Duration directly (doc):

delay += rand.N(delay/8 + 1)

Verifying

Maximum jitter per attempt before and after. This is deterministic, so it can be checked by running the following code:

package main

import (
	"fmt"
	"time"
)

func main() {
	for retry := range 7 {
		delay := 100 * time.Millisecond << retry
		// max of time.Duration(rand.Int64N(1 + (delay.Milliseconds() >> 3)))
		before := time.Duration(delay.Milliseconds() >> 3)
		// max of rand.N(delay/8 + 1)
		after := delay / 8                                 
		fmt.Printf("attempt %d: delay %-6v jitter before <= %-6v after <= %v\n", retry, delay, before, after)
	}
}
attempt 0: delay 100ms  jitter before <= 12ns   after <= 12.5ms
attempt 1: delay 200ms  jitter before <= 25ns   after <= 25ms
attempt 2: delay 400ms  jitter before <= 50ns   after <= 50ms
attempt 3: delay 800ms  jitter before <= 100ns  after <= 100ms
attempt 4: delay 1.6s   jitter before <= 200ns  after <= 200ms
attempt 5: delay 3.2s   jitter before <= 400ns  after <= 400ms
attempt 6: delay 6.4s   jitter before <= 800ns  after <= 800ms

Effect under load

Measured with 750 clients connecting at once to a dbus-daemon already at its per-user connection limit (Ubuntu 26.04, dbus-daemon 1.16.2, the 7 attempts from the code):

jitter clients that exhausted all 7 attempts wall time for the burst
before (nanoseconds) 76 13.35 s
after (0 to 1/8 of delay) 0 7.90 s

@hakman
hakman requested a review from a team as a code owner October 7, 2026 12:18

@kolyshkin kolyshkin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

Can you add

Fixes: cd71e92 ("systemd: retry when the dbus connection returns EAGAIN")

footer?

@kolyshkin kolyshkin added this to the 0.1.1 milestone Oct 7, 2026

@thaJeztah thaJeztah left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@kolyshkin didn't merge yet because your comment w.r.t. the commit footer, but good to go otherwise?

@hakman
hakman force-pushed the systemd-dbus-retry-jitter branch 2 times, most recently from 4b7ca11 to 7c53df9 Compare October 8, 2026 06:50
@hakman

hakman commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Added the footer as requested. Thank you both for the review.

@AkihiroSuda

Copy link
Copy Markdown
Member

GPG signature seems invalid

The email in this signature doesn’t match the committer email.
GPG Key ID: 1F476A1AD1D6829B

The jitter added to the backoff delay in newConnection is computed in
milliseconds and then converted to time.Duration as is, which makes it
nanoseconds: at most 800 ns, rather than the ~12.5% of the delay the
comment above promises. As a result, clients refused at the same time
retry at the same time.

Fix this by making the jitter 0 to 1/8 of the delay, as intended.

Fixes: cd71e92 ("systemd: retry when the dbus connection returns EAGAIN")

Signed-off-by: Ciprian Hacman <ciprian@hakman.dev>
@hakman
hakman force-pushed the systemd-dbus-retry-jitter branch from 7c53df9 to ac3fe77 Compare October 8, 2026 08:20
@hakman

hakman commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

GPG signature seems invalid

The email in this signature doesn’t match the committer email.
GPG Key ID: 1F476A1AD1D6829B

Thanks for catching this @AkihiroSuda, fixed now.

@AkihiroSuda
AkihiroSuda merged commit 8119776 into opencontainers:main Oct 8, 2026
15 checks passed
@hakman
hakman deleted the systemd-dbus-retry-jitter branch October 8, 2026 09:37
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.

4 participants