flock-agent: GC orphaned allocations; retry birdc on socket-not-ready (#5)
flock / release (push) Successful in 1m7s

flock-agent: GC orphaned allocations; retry birdc on socket-not-ready
This commit was merged in pull request #5.
This commit is contained in:
ops
2026-08-17 04:24:13 +00:00
parent 197bc6f3b8
commit 31088ca8f2
5 changed files with 247 additions and 8 deletions
+40 -8
View File
@@ -8,6 +8,7 @@ import (
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
"time"
@@ -137,6 +138,15 @@ func (b *BirdManager) scheduleReload() {
})
}
// birdcMaxAttempts and birdcRetryDelay bound the startup-socket retry loop.
// BIRD may not have bound its control socket yet when flock-agent first
// tries to configure it; 20 × 500 ms = 10 s covers the typical BIRD
// startup window without blocking indefinitely.
const (
birdcMaxAttempts = 20
birdcRetryDelay = 500 * time.Millisecond
)
func (b *BirdManager) reload() {
birdctl := b.BirdctlPath
if birdctl == "" {
@@ -146,18 +156,40 @@ func (b *BirdManager) reload() {
if socket == "" {
socket = "/run/flock/bird.ctl"
}
cmd := exec.Command(birdctl, "-s", socket, "configure")
out, err := cmd.CombinedOutput()
if err != nil {
// First-run case: bird may not be ready yet — retry on next change.
if errors.Is(err, exec.ErrNotFound) || os.IsNotExist(err) {
b.Logger.Warn("birdc not available", "err", err)
for attempt := 1; attempt <= birdcMaxAttempts; attempt++ {
if attempt > 1 {
time.Sleep(birdcRetryDelay)
}
// Socket absent → BIRD hasn't bound it yet; retry.
if _, err := os.Stat(socket); os.IsNotExist(err) {
b.Logger.Debug("birdc socket not ready, retrying",
"attempt", attempt, "socket", socket)
continue
}
cmd := exec.Command(birdctl, "-s", socket, "configure")
out, err := cmd.CombinedOutput()
if err == nil {
b.Logger.Info("birdc configure ok", "out", string(out))
return
}
b.Logger.Warn("birdc reload failed", "err", err, "out", string(out))
if errors.Is(err, exec.ErrNotFound) {
b.Logger.Warn("birdc not found", "err", err)
return
}
outStr := string(out)
// "Unable to connect" means BIRD exists but isn't listening yet.
if strings.Contains(outStr, "Unable to connect") {
b.Logger.Debug("birdc not ready, retrying",
"attempt", attempt, "err", err)
continue
}
// Any other failure (syntax error, etc.) is not retriable.
b.Logger.Warn("birdc reload failed", "err", err, "out", outStr)
return
}
b.Logger.Info("birdc configure ok", "out", string(out))
b.Logger.Error("birdc configure gave up after retries",
"socket", socket, "attempts", birdcMaxAttempts)
}
// SummaryRoutes installs blackhole kernel routes for each NodeConfig CIDR.