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

No asynchronous response when service is stopped #416

Open
ndeubert opened this issue Feb 6, 2023 · 3 comments
Open

No asynchronous response when service is stopped #416

ndeubert opened this issue Feb 6, 2023 · 3 comments

Comments

@ndeubert
Copy link

ndeubert commented Feb 6, 2023

I noticed when using this code:

func isChanged(prev *dbus.UnitStatus, curr *dbus.UnitStatus) bool {
	if prev.ActiveState != curr.ActiveState {
		return true
	}
	return false
}

func (o *Object) filterUnit(unit string) bool {
	if unit == o.cfg.PlatCfg.ServiceName1|| unit == o.cfg.PlatCfg.ServiceName2{
		return false
	}
	return true
}
...
o.asyncstatus, o.asyncerr = o.conn.SubscribeUnitsCustom(1*time.Second, 1, isChanged, o.filterUnit)

I do not get any events from the asyncstatus channel when the service is stopped in a terminal with sudo systemctl stop service1 like I do when I start a service with
id, err := o.conn.StartUnitContext(o.ctx, svcName, "replace", o.async) or sudo systemctl start service1

Even if I stop the service programmatically with
id, usererr := o.conn.StopUnitContext(o.ctx, o.cfg.PlatCfg.ServiceName1, "replace", o.async)
I only see "done" on the async channel.

If I want to find out about these events do I need to use the dbus interface directly? Do I need to poll myself or use o.asyncstatus, o.asyncerr = o.conn.SubscribeUnits(1 * time.Second) and check if it goes away?. If I kill the process manually then I do get a "failed" event on the asyncstatus channel. I didn't see any mention of this being expected behavior in the documentation, but it seems odd not to be supported given the rest of the behavior. Thanks.

@vlw
Copy link

vlw commented Mar 18, 2024

I have same issue :(

	updates, errors := conn.SubscribeUnitsCustom(0, 10, isChanged, filterUnit)

	go func() {
		for err := range errors {
			log.Printf("Error: %s", err)
		}
	}()

	for update := range updates {
		for sName, status := range update {
			if status != nil {
				log.Printf("Service %s ActiveState changed to: %s\n", sName, status.ActiveState)
			} else {
				log.Printf("Service %s: no status\n", sName)
			}
		}
	}

log when I start/stop service many times:

2024/03/19 01:39:34 Service s-kek-1.service ActiveState changed to: active
2024/03/19 01:39:57 Service s-kek-1.service ActiveState changed to: deactivating
2024/03/19 01:39:57 Service s-kek-1.service: no status
2024/03/19 01:40:02 Service s-kek-1.service ActiveState changed to: active
2024/03/19 01:40:07 Service s-kek-1.service: no status
2024/03/19 01:40:12 Service s-kek-1.service ActiveState changed to: active

sometimes I see "deactivating" but always see "no status" when service stopped

BTW I see all logs in dbus monitor:
dbus-monitor --system "type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path='/org/freedesktop/systemd1/unit/s_2dkek_2d1_2eservice'" | awk '/string "ActiveState"/ { getline; print $0 }'
terminal output:

         variant             string "active"
         variant             string "active"
         variant             string "deactivating"
         variant             string "inactive"
         variant             string "inactive"
         variant             string "inactive"
         variant             string "active"
         variant             string "active"
         variant             string "active"

@vlw
Copy link

vlw commented Mar 19, 2024

@ndeubert solution found!

package main

import (
	"fmt"
	"github.com/godbus/dbus/v5"
	"log"
	"strings"
)

func main() {
	conn, err := dbus.SystemBus()
	if err != nil {
		log.Fatalf("Failed to connect to System Bus: %v", err)
	}

	var rules = "type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',arg0namespace='org.freedesktop.systemd1.Unit'"
	conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, rules)
	fmt.Println("Subscribed to PropertiesChanged signals for systemd units")

	c := make(chan *dbus.Signal, 10)
	conn.Signal(c)

	for v := range c {
		handleSignal(v)
	}
}

func handleSignal(v *dbus.Signal) {
	if len(v.Body) >= 3 {
		var unitPath dbus.ObjectPath
		var changedProps map[string]dbus.Variant
		//var iface string

		//iface = v.Body[0].(string)
		changedProps = v.Body[1].(map[string]dbus.Variant)
		unitPath = v.Path

		//fmt.Printf("Signal from interface %s for unit %s\n", iface, unitPath)

		for propName, propValue := range changedProps {
			if propName == "ActiveState" {
				//fmt.Println("ActiveState changed")
				unitName := strings.Replace(string(unitPath), "/org/freedesktop/systemd1/unit/", "", 1)
				unitName = strings.Replace(unitName, "_2e", ".", -1)
				unitName = strings.Replace(unitName, "_2d", "-", -1)
				unitName = strings.Replace(unitName, "_5f", "_", -1)
				fmt.Printf("Unit: %s, ActiveState: %s\n", unitName, propValue.Value().(string))
			}
		}
	}
}

Output:

Subscribed to PropertiesChanged signals for systemd units
Unit: php8.3-fpm.service, ActiveState: active
Unit: php8.3-fpm.service, ActiveState: active
Unit: php8.3-fpm.service, ActiveState: active
Unit: php8.3-fpm.service, ActiveState: active
Unit: php8.3-fpm.service, ActiveState: active
Unit: php8.3-fpm.service, ActiveState: active
Unit: user-1157.slice, ActiveState: inactive
Unit: user-1157.slice, ActiveState: active
Unit: user-runtime-dir_401157.service, ActiveState: inactive
Unit: user-runtime-dir_401157.service, ActiveState: activating
Unit: user-1157.slice, ActiveState: active
Unit: user-runtime-dir_401157.service, ActiveState: active
Unit: user-runtime-dir_401157.service, ActiveState: active
Unit: user_401157.service, ActiveState: inactive
Unit: user_401157.service, ActiveState: activating
Unit: user_401157.service, ActiveState: activating
Unit: user_401157.service, ActiveState: active
Unit: user_401157.service, ActiveState: active
Unit: user_401157.service, ActiveState: active
Unit: session-18886.scope, ActiveState: inactive
Unit: session-18886.scope, ActiveState: active
Unit: session-18886.scope, ActiveState: active
Unit: session-18886.scope, ActiveState: inactive
Unit: user-1158.slice, ActiveState: inactive
Unit: user-1158.slice, ActiveState: active
Unit: user-runtime-dir_401158.service, ActiveState: inactive
Unit: user-runtime-dir_401158.service, ActiveState: activating
Unit: user-1158.slice, ActiveState: active
Unit: user-runtime-dir_401158.service, ActiveState: active
Unit: user-runtime-dir_401158.service, ActiveState: active
Unit: user_401158.service, ActiveState: inactive

@ndeubert
Copy link
Author

Ah cool. thank you for following up

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

No branches or pull requests

2 participants