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

dbus: Add GetUnitByPID #298

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions dbus/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,16 @@ func (c *Conn) listUnitsInternal(f storeFunc) ([]UnitStatus, error) {
return status, nil
}

// GetUnitByPID returns the object path of the unit a process ID belongs to.
// The pid must refer to an existing process on the system.
func (c *Conn) GetUnitByPID(pid uint32) (dbus.ObjectPath, error) {
var op dbus.ObjectPath
if err := c.sysobj.Call("org.freedesktop.systemd1.Manager.GetUnitByPID", 0, uint(pid)).Store(&op); err != nil {
return dbus.ObjectPath(""), err
}
return op, nil
}

// ListUnits returns an array with all currently loaded units. Note that
// units may be known by multiple names at the same time, and hence there might
// be more unit names loaded than actual units behind them.
Expand Down
53 changes: 53 additions & 0 deletions dbus/methods_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"path"
"path/filepath"
"reflect"
"strings"
"syscall"
"testing"
"time"
Expand Down Expand Up @@ -1539,3 +1540,55 @@ func TestUnitName(t *testing.T) {
}
}
}

func assertNoError(t *testing.T, err error) {
if err != nil {
t.Fatal(err)
}
}

func assertEqualStr(t *testing.T, shouldBe, target string) {
if target != shouldBe {
t.Fatalf("expected %q to equal %q", target, shouldBe)
}
}

func TestGetUnitByPID(t *testing.T) {
target := "get-unit-pid.service"
conn := setupConn(t)
defer conn.Close()

setupUnit(target, conn, t)
linkUnit(target, conn, t)

reschan := make(chan string)
_, err := conn.StartUnit(target, "replace", reschan)
assertNoError(t, err)

job := <-reschan
assertEqualStr(t, "done", job)
prop, err := conn.GetServiceProperty("get-unit-pid.service", "MainPID")
assertNoError(t, err)

pid, ok := prop.Value.Value().(uint32)
if !ok {
t.Fatalf("expected MainPID to be uint32, got value %v of type %T", prop.Value, prop.Value)
}
if pid == 0 {
t.Fatal("expected MainPID to be greater than 0")
}

objectPath, err := conn.GetUnitByPID(pid)
assertNoError(t, err)
if strings.HasSuffix(string(objectPath), "_2eslice") {
// in ubuntu:18.04 the top-level root slice container is the unit that gets returned
assertEqualStr(t, "/org/freedesktop/systemd1/unit/_2d_2eslice", string(objectPath))
} else {
// otherwise, the service itself is returned
assertEqualStr(t, "/org/freedesktop/systemd1/unit/get_2dunit_2dpid_2eservice", string(objectPath))
}

_, err = conn.StopUnit(target, "replace", reschan)
assertNoError(t, err)
<-reschan
}
5 changes: 5 additions & 0 deletions fixtures/get-unit-pid.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[Unit]
Description=get unit pid

[Service]
ExecStart=/bin/sleep 400