-
Notifications
You must be signed in to change notification settings - Fork 329
Description
Describe the bug
When using SetSubStateSubscriber to monitor systemd unit state changes, the subscriber continuously receives repeated events for a unit that is in the "dead" SubState. This causes an infinite stream of events even though the unit's state hasn't actually changed.
To Reproduce
- Create a simple systemd service (e.g.,
hello-systemd.service) - Subscribe using
SetSubStateSubscriber - Start and then stop the service:
sudo systemctl stop hello-systemd - Observe the channel receiving thousands of repeated events per second
Minimal reproduction code:
package main
import (
"context"
"fmt"
"strings"
"github.com/coreos/go-systemd/v22/dbus"
)
func main() {
ctx := context.Background()
conn, err := dbus.NewSystemdConnectionContext(ctx)
if err != nil {
panic(err)
}
defer conn.Close()
if err := conn.Subscribe(); err != nil {
panic(err)
}
defer conn.Unsubscribe()
statusChan := make(chan *dbus.SubStateUpdate, 100)
errChan := make(chan error, 10)
conn.SetSubStateSubscriber(statusChan, errChan)
eventCount := 0
for update := range statusChan {
if strings.HasSuffix(update.UnitName, ".service") {
eventCount++
fmt.Printf("event=%d unit=%s SubState=%s\n", eventCount, update.UnitName, update.SubState)
}
}
}Steps:
# Terminal 1: Run the subscriber
go run main.go
# Terminal 2: Stop a service
sudo systemctl stop hello-systemd
# Observe Terminal 1 flooding with events like:
# event=1 unit=hello-systemd.service SubState=dead
# event=2 unit=hello-systemd.service SubState=dead
# event=3 unit=hello-systemd.service SubState=dead
# ... (thousands per second, never stops)Expected behavior
SetSubStateSubscriber should only send an event when the SubState actually changes, not repeatedly for the same state. Once a unit transitions to "dead", it should send one event and then remain silent until the next state change.
Actual behavior
The subscriber continuously floods the channel with repeated "dead" state events, making it unusable for monitoring service state changes.
Environment
- go-systemd version: v22.5.0
- Go version: 1.24
- OS: Ubuntu 24.04 (systemd 255)
Workaround
Using SetPropertiesSubscriber instead works correctly - it only fires when D-Bus actually sends a PropertiesChanged signal:
propsChan := make(chan *dbus.PropertiesUpdate, 100)
errChan := make(chan error, 10)
conn.SetPropertiesSubscriber(propsChan, errChan)Additional context
Our use case is a security monitoring agent that needs to detect when systemd services start/stop. SetSubStateSubscriber seemed ideal but the flooding issue makes it unusable. We switched to SetPropertiesSubscriber which works correctly but requires filtering for ActiveState changes manually.