vendor: update go-systemd and godbus

Signed-off-by: Shiming Zhang <wzshiming@foxmail.com>
This commit is contained in:
Shiming Zhang
2021-04-01 20:54:13 +08:00
parent bed4d89f57
commit adf733fa64
22 changed files with 734 additions and 238 deletions
+2 -2
View File
@@ -6,10 +6,10 @@ require (
github.com/checkpoint-restore/go-criu/v5 v5.0.0 github.com/checkpoint-restore/go-criu/v5 v5.0.0
github.com/cilium/ebpf v0.2.0 github.com/cilium/ebpf v0.2.0
github.com/containerd/console v1.0.1 github.com/containerd/console v1.0.1
github.com/coreos/go-systemd/v22 v22.1.0 github.com/coreos/go-systemd/v22 v22.3.1
github.com/cyphar/filepath-securejoin v0.2.2 github.com/cyphar/filepath-securejoin v0.2.2
github.com/docker/go-units v0.4.0 github.com/docker/go-units v0.4.0
github.com/godbus/dbus/v5 v5.0.3 github.com/godbus/dbus/v5 v5.0.4
github.com/moby/sys/mountinfo v0.4.0 github.com/moby/sys/mountinfo v0.4.0
github.com/mrunalp/fileutils v0.5.0 github.com/mrunalp/fileutils v0.5.0
github.com/opencontainers/runtime-spec v1.0.3-0.20210316141917-a8c4a9ee0f6b github.com/opencontainers/runtime-spec v1.0.3-0.20210316141917-a8c4a9ee0f6b
+4 -6
View File
@@ -8,8 +8,8 @@ github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/containerd/console v1.0.1 h1:u7SFAJyRqWcG6ogaMAx3KjSTy1e3hT9QxqX7Jco7dRc= github.com/containerd/console v1.0.1 h1:u7SFAJyRqWcG6ogaMAx3KjSTy1e3hT9QxqX7Jco7dRc=
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg= github.com/coreos/go-systemd/v22 v22.3.1 h1:7OO2CXWMYNDdaAzP51t4lCCZWwpQHmvPbm9sxWjm3So=
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.3.1/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg= github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
@@ -20,8 +20,8 @@ github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -97,7 +97,6 @@ golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -125,7 +124,6 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// +build !windows
// Package activation implements primitives for systemd socket activation. // Package activation implements primitives for systemd socket activation.
package activation package activation
+21
View File
@@ -0,0 +1,21 @@
// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package activation
import "os"
func Files(unsetEnv bool) []*os.File {
return nil
}
+35 -10
View File
@@ -16,6 +16,7 @@
package dbus package dbus
import ( import (
"context"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"os" "os"
@@ -112,39 +113,63 @@ type Conn struct {
// New establishes a connection to any available bus and authenticates. // New establishes a connection to any available bus and authenticates.
// Callers should call Close() when done with the connection. // Callers should call Close() when done with the connection.
// Deprecated: use NewWithContext instead
func New() (*Conn, error) { func New() (*Conn, error) {
conn, err := NewSystemConnection() return NewWithContext(context.Background())
}
// NewWithContext same as New with context
func NewWithContext(ctx context.Context) (*Conn, error) {
conn, err := NewSystemConnectionContext(ctx)
if err != nil && os.Geteuid() == 0 { if err != nil && os.Geteuid() == 0 {
return NewSystemdConnection() return NewSystemdConnectionContext(ctx)
} }
return conn, err return conn, err
} }
// NewSystemConnection establishes a connection to the system bus and authenticates. // NewSystemConnection establishes a connection to the system bus and authenticates.
// Callers should call Close() when done with the connection // Callers should call Close() when done with the connection
// Deprecated: use NewSystemConnectionContext instead
func NewSystemConnection() (*Conn, error) { func NewSystemConnection() (*Conn, error) {
return NewSystemConnectionContext(context.Background())
}
// NewSystemConnectionContext same as NewSystemConnection with context
func NewSystemConnectionContext(ctx context.Context) (*Conn, error) {
return NewConnection(func() (*dbus.Conn, error) { return NewConnection(func() (*dbus.Conn, error) {
return dbusAuthHelloConnection(dbus.SystemBusPrivate) return dbusAuthHelloConnection(ctx, dbus.SystemBusPrivate)
}) })
} }
// NewUserConnection establishes a connection to the session bus and // NewUserConnection establishes a connection to the session bus and
// authenticates. This can be used to connect to systemd user instances. // authenticates. This can be used to connect to systemd user instances.
// Callers should call Close() when done with the connection. // Callers should call Close() when done with the connection.
// Deprecated: use NewUserConnectionContext instead
func NewUserConnection() (*Conn, error) { func NewUserConnection() (*Conn, error) {
return NewUserConnectionContext(context.Background())
}
// NewUserConnectionContext same as NewUserConnection with context
func NewUserConnectionContext(ctx context.Context) (*Conn, error) {
return NewConnection(func() (*dbus.Conn, error) { return NewConnection(func() (*dbus.Conn, error) {
return dbusAuthHelloConnection(dbus.SessionBusPrivate) return dbusAuthHelloConnection(ctx, dbus.SessionBusPrivate)
}) })
} }
// NewSystemdConnection establishes a private, direct connection to systemd. // NewSystemdConnection establishes a private, direct connection to systemd.
// This can be used for communicating with systemd without a dbus daemon. // This can be used for communicating with systemd without a dbus daemon.
// Callers should call Close() when done with the connection. // Callers should call Close() when done with the connection.
// Deprecated: use NewSystemdConnectionContext instead
func NewSystemdConnection() (*Conn, error) { func NewSystemdConnection() (*Conn, error) {
return NewSystemdConnectionContext(context.Background())
}
// NewSystemdConnectionContext same as NewSystemdConnection with context
func NewSystemdConnectionContext(ctx context.Context) (*Conn, error) {
return NewConnection(func() (*dbus.Conn, error) { return NewConnection(func() (*dbus.Conn, error) {
// We skip Hello when talking directly to systemd. // We skip Hello when talking directly to systemd.
return dbusAuthConnection(func(opts ...dbus.ConnOption) (*dbus.Conn, error) { return dbusAuthConnection(ctx, func(opts ...dbus.ConnOption) (*dbus.Conn, error) {
return dbus.Dial("unix:path=/run/systemd/private") return dbus.Dial("unix:path=/run/systemd/private", opts...)
}) })
}) })
} }
@@ -201,8 +226,8 @@ func (c *Conn) GetManagerProperty(prop string) (string, error) {
return variant.String(), nil return variant.String(), nil
} }
func dbusAuthConnection(createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) { func dbusAuthConnection(ctx context.Context, createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) {
conn, err := createBus() conn, err := createBus(dbus.WithContext(ctx))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -221,8 +246,8 @@ func dbusAuthConnection(createBus func(opts ...dbus.ConnOption) (*dbus.Conn, err
return conn, nil return conn, nil
} }
func dbusAuthHelloConnection(createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) { func dbusAuthHelloConnection(ctx context.Context, createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) {
conn, err := dbusAuthConnection(createBus) conn, err := dbusAuthConnection(ctx, createBus)
if err != nil { if err != nil {
return nil, err return nil, err
} }
+287 -38
View File
@@ -15,6 +15,7 @@
package dbus package dbus
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"path" "path"
@@ -23,6 +24,18 @@ import (
"github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
) )
// Who can be used to specify which process to kill in the unit via the KillUnitWithTarget API
type Who string
const (
// All sends the signal to all processes in the unit
All Who = "all"
// Main sends the signal to the main process of the unit
Main Who = "main"
// Control sends the signal to the control process of the unit
Control Who = "control"
)
func (c *Conn) jobComplete(signal *dbus.Signal) { func (c *Conn) jobComplete(signal *dbus.Signal) {
var id uint32 var id uint32
var job dbus.ObjectPath var job dbus.ObjectPath
@@ -38,14 +51,14 @@ func (c *Conn) jobComplete(signal *dbus.Signal) {
c.jobListener.Unlock() c.jobListener.Unlock()
} }
func (c *Conn) startJob(ch chan<- string, job string, args ...interface{}) (int, error) { func (c *Conn) startJob(ctx context.Context, ch chan<- string, job string, args ...interface{}) (int, error) {
if ch != nil { if ch != nil {
c.jobListener.Lock() c.jobListener.Lock()
defer c.jobListener.Unlock() defer c.jobListener.Unlock()
} }
var p dbus.ObjectPath var p dbus.ObjectPath
err := c.sysobj.Call(job, 0, args...).Store(&p) err := c.sysobj.CallWithContext(ctx, job, 0, args...).Store(&p)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@@ -90,43 +103,85 @@ func (c *Conn) startJob(ch chan<- string, job string, args ...interface{}) (int,
// should not be considered authoritative. // should not be considered authoritative.
// //
// If an error does occur, it will be returned to the user alongside a job ID of 0. // If an error does occur, it will be returned to the user alongside a job ID of 0.
// Deprecated: use StartUnitContext instead
func (c *Conn) StartUnit(name string, mode string, ch chan<- string) (int, error) { func (c *Conn) StartUnit(name string, mode string, ch chan<- string) (int, error) {
return c.startJob(ch, "org.freedesktop.systemd1.Manager.StartUnit", name, mode) return c.StartUnitContext(context.Background(), name, mode, ch)
}
// StartUnitContext same as StartUnit with context
func (c *Conn) StartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.StartUnit", name, mode)
} }
// StopUnit is similar to StartUnit but stops the specified unit rather // StopUnit is similar to StartUnit but stops the specified unit rather
// than starting it. // than starting it.
// Deprecated: use StopUnitContext instead
func (c *Conn) StopUnit(name string, mode string, ch chan<- string) (int, error) { func (c *Conn) StopUnit(name string, mode string, ch chan<- string) (int, error) {
return c.startJob(ch, "org.freedesktop.systemd1.Manager.StopUnit", name, mode) return c.StopUnitContext(context.Background(), name, mode, ch)
}
// StopUnitContext same as StopUnit with context
func (c *Conn) StopUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.StopUnit", name, mode)
} }
// ReloadUnit reloads a unit. Reloading is done only if the unit is already running and fails otherwise. // ReloadUnit reloads a unit. Reloading is done only if the unit is already running and fails otherwise.
// Deprecated: use ReloadUnitContext instead
func (c *Conn) ReloadUnit(name string, mode string, ch chan<- string) (int, error) { func (c *Conn) ReloadUnit(name string, mode string, ch chan<- string) (int, error) {
return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadUnit", name, mode) return c.ReloadUnitContext(context.Background(), name, mode, ch)
}
// ReloadUnitContext same as ReloadUnit with context
func (c *Conn) ReloadUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.ReloadUnit", name, mode)
} }
// RestartUnit restarts a service. If a service is restarted that isn't // RestartUnit restarts a service. If a service is restarted that isn't
// running it will be started. // running it will be started.
// Deprecated: use RestartUnitContext instead
func (c *Conn) RestartUnit(name string, mode string, ch chan<- string) (int, error) { func (c *Conn) RestartUnit(name string, mode string, ch chan<- string) (int, error) {
return c.startJob(ch, "org.freedesktop.systemd1.Manager.RestartUnit", name, mode) return c.RestartUnitContext(context.Background(), name, mode, ch)
}
// RestartUnitContext same as RestartUnit with context
func (c *Conn) RestartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.RestartUnit", name, mode)
} }
// TryRestartUnit is like RestartUnit, except that a service that isn't running // TryRestartUnit is like RestartUnit, except that a service that isn't running
// is not affected by the restart. // is not affected by the restart.
// Deprecated: use TryRestartUnitContext instead
func (c *Conn) TryRestartUnit(name string, mode string, ch chan<- string) (int, error) { func (c *Conn) TryRestartUnit(name string, mode string, ch chan<- string) (int, error) {
return c.startJob(ch, "org.freedesktop.systemd1.Manager.TryRestartUnit", name, mode) return c.TryRestartUnitContext(context.Background(), name, mode, ch)
}
// TryRestartUnitContext same as TryRestartUnit with context
func (c *Conn) TryRestartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.TryRestartUnit", name, mode)
} }
// ReloadOrRestartUnit attempts a reload if the unit supports it and use a restart // ReloadOrRestartUnit attempts a reload if the unit supports it and use a restart
// otherwise. // otherwise.
// Deprecated: use ReloadOrRestartUnitContext instead
func (c *Conn) ReloadOrRestartUnit(name string, mode string, ch chan<- string) (int, error) { func (c *Conn) ReloadOrRestartUnit(name string, mode string, ch chan<- string) (int, error) {
return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadOrRestartUnit", name, mode) return c.ReloadOrRestartUnitContext(context.Background(), name, mode, ch)
}
// ReloadOrRestartUnitContext same as ReloadOrRestartUnit with context
func (c *Conn) ReloadOrRestartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.ReloadOrRestartUnit", name, mode)
} }
// ReloadOrTryRestartUnit attempts a reload if the unit supports it and use a "Try" // ReloadOrTryRestartUnit attempts a reload if the unit supports it and use a "Try"
// flavored restart otherwise. // flavored restart otherwise.
// Deprecated: use ReloadOrTryRestartUnitContext instead
func (c *Conn) ReloadOrTryRestartUnit(name string, mode string, ch chan<- string) (int, error) { func (c *Conn) ReloadOrTryRestartUnit(name string, mode string, ch chan<- string) (int, error) {
return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadOrTryRestartUnit", name, mode) return c.ReloadOrTryRestartUnitContext(context.Background(), name, mode, ch)
}
// ReloadOrTryRestartUnitContext same as ReloadOrTryRestartUnit with context
func (c *Conn) ReloadOrTryRestartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.ReloadOrTryRestartUnit", name, mode)
} }
// StartTransientUnit() may be used to create and start a transient unit, which // StartTransientUnit() may be used to create and start a transient unit, which
@@ -134,28 +189,57 @@ func (c *Conn) ReloadOrTryRestartUnit(name string, mode string, ch chan<- string
// system is rebooted. name is the unit name including suffix, and must be // system is rebooted. name is the unit name including suffix, and must be
// unique. mode is the same as in StartUnit(), properties contains properties // unique. mode is the same as in StartUnit(), properties contains properties
// of the unit. // of the unit.
// Deprecated: use StartTransientUnitContext instead
func (c *Conn) StartTransientUnit(name string, mode string, properties []Property, ch chan<- string) (int, error) { func (c *Conn) StartTransientUnit(name string, mode string, properties []Property, ch chan<- string) (int, error) {
return c.startJob(ch, "org.freedesktop.systemd1.Manager.StartTransientUnit", name, mode, properties, make([]PropertyCollection, 0)) return c.StartTransientUnitContext(context.Background(), name, mode, properties, ch)
}
// StartTransientUnitContext same as StartTransientUnit with context
func (c *Conn) StartTransientUnitContext(ctx context.Context, name string, mode string, properties []Property, ch chan<- string) (int, error) {
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.StartTransientUnit", name, mode, properties, make([]PropertyCollection, 0))
} }
// KillUnit takes the unit name and a UNIX signal number to send. All of the unit's // KillUnit takes the unit name and a UNIX signal number to send. All of the unit's
// processes are killed. // processes are killed.
// Deprecated: use KillUnitContext instead
func (c *Conn) KillUnit(name string, signal int32) { func (c *Conn) KillUnit(name string, signal int32) {
c.sysobj.Call("org.freedesktop.systemd1.Manager.KillUnit", 0, name, "all", signal).Store() c.KillUnitContext(context.Background(), name, signal)
}
// KillUnitContext same as KillUnit with context
func (c *Conn) KillUnitContext(ctx context.Context, name string, signal int32) {
c.KillUnitWithTarget(ctx, name, All, signal)
}
// KillUnitWithTarget is like KillUnitContext, but allows you to specify which process in the unit to send the signal to
func (c *Conn) KillUnitWithTarget(ctx context.Context, name string, target Who, signal int32) error {
return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.KillUnit", 0, name, string(target), signal).Store()
} }
// ResetFailedUnit resets the "failed" state of a specific unit. // ResetFailedUnit resets the "failed" state of a specific unit.
// Deprecated: use ResetFailedUnitContext instead
func (c *Conn) ResetFailedUnit(name string) error { func (c *Conn) ResetFailedUnit(name string) error {
return c.sysobj.Call("org.freedesktop.systemd1.Manager.ResetFailedUnit", 0, name).Store() return c.ResetFailedUnitContext(context.Background(), name)
}
// ResetFailedUnitContext same as ResetFailedUnit with context
func (c *Conn) ResetFailedUnitContext(ctx context.Context, name string) error {
return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ResetFailedUnit", 0, name).Store()
} }
// SystemState returns the systemd state. Equivalent to `systemctl is-system-running`. // SystemState returns the systemd state. Equivalent to `systemctl is-system-running`.
// Deprecated: use SystemStateContext instead
func (c *Conn) SystemState() (*Property, error) { func (c *Conn) SystemState() (*Property, error) {
return c.SystemStateContext(context.Background())
}
// SystemStateContext same as SystemState with context
func (c *Conn) SystemStateContext(ctx context.Context) (*Property, error) {
var err error var err error
var prop dbus.Variant var prop dbus.Variant
obj := c.sysconn.Object("org.freedesktop.systemd1", "/org/freedesktop/systemd1") obj := c.sysconn.Object("org.freedesktop.systemd1", "/org/freedesktop/systemd1")
err = obj.Call("org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.systemd1.Manager", "SystemState").Store(&prop) err = obj.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.systemd1.Manager", "SystemState").Store(&prop)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -164,7 +248,7 @@ func (c *Conn) SystemState() (*Property, error) {
} }
// getProperties takes the unit path and returns all of its dbus object properties, for the given dbus interface // getProperties takes the unit path and returns all of its dbus object properties, for the given dbus interface
func (c *Conn) getProperties(path dbus.ObjectPath, dbusInterface string) (map[string]interface{}, error) { func (c *Conn) getProperties(ctx context.Context, path dbus.ObjectPath, dbusInterface string) (map[string]interface{}, error) {
var err error var err error
var props map[string]dbus.Variant var props map[string]dbus.Variant
@@ -173,7 +257,7 @@ func (c *Conn) getProperties(path dbus.ObjectPath, dbusInterface string) (map[st
} }
obj := c.sysconn.Object("org.freedesktop.systemd1", path) obj := c.sysconn.Object("org.freedesktop.systemd1", path)
err = obj.Call("org.freedesktop.DBus.Properties.GetAll", 0, dbusInterface).Store(&props) err = obj.CallWithContext(ctx, "org.freedesktop.DBus.Properties.GetAll", 0, dbusInterface).Store(&props)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -187,23 +271,41 @@ func (c *Conn) getProperties(path dbus.ObjectPath, dbusInterface string) (map[st
} }
// GetUnitProperties takes the (unescaped) unit name and returns all of its dbus object properties. // GetUnitProperties takes the (unescaped) unit name and returns all of its dbus object properties.
// Deprecated: use GetUnitPropertiesContext instead
func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) { func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) {
return c.GetUnitPropertiesContext(context.Background(), unit)
}
// GetUnitPropertiesContext same as GetUnitPropertiesContext with context
func (c *Conn) GetUnitPropertiesContext(ctx context.Context, unit string) (map[string]interface{}, error) {
path := unitPath(unit) path := unitPath(unit)
return c.getProperties(path, "org.freedesktop.systemd1.Unit") return c.getProperties(ctx, path, "org.freedesktop.systemd1.Unit")
} }
// GetUnitPathProperties takes the (escaped) unit path and returns all of its dbus object properties. // GetUnitPathProperties takes the (escaped) unit path and returns all of its dbus object properties.
// Deprecated: use GetUnitPathPropertiesContext instead
func (c *Conn) GetUnitPathProperties(path dbus.ObjectPath) (map[string]interface{}, error) { func (c *Conn) GetUnitPathProperties(path dbus.ObjectPath) (map[string]interface{}, error) {
return c.getProperties(path, "org.freedesktop.systemd1.Unit") return c.GetUnitPathPropertiesContext(context.Background(), path)
}
// GetUnitPathPropertiesContext same as GetUnitPathProperties with context
func (c *Conn) GetUnitPathPropertiesContext(ctx context.Context, path dbus.ObjectPath) (map[string]interface{}, error) {
return c.getProperties(ctx, path, "org.freedesktop.systemd1.Unit")
} }
// GetAllProperties takes the (unescaped) unit name and returns all of its dbus object properties. // GetAllProperties takes the (unescaped) unit name and returns all of its dbus object properties.
// Deprecated: use GetAllPropertiesContext instead
func (c *Conn) GetAllProperties(unit string) (map[string]interface{}, error) { func (c *Conn) GetAllProperties(unit string) (map[string]interface{}, error) {
path := unitPath(unit) return c.GetAllPropertiesContext(context.Background(), unit)
return c.getProperties(path, "")
} }
func (c *Conn) getProperty(unit string, dbusInterface string, propertyName string) (*Property, error) { // GetAllPropertiesContext same as GetAllProperties with context
func (c *Conn) GetAllPropertiesContext(ctx context.Context, unit string) (map[string]interface{}, error) {
path := unitPath(unit)
return c.getProperties(ctx, path, "")
}
func (c *Conn) getProperty(ctx context.Context, unit string, dbusInterface string, propertyName string) (*Property, error) {
var err error var err error
var prop dbus.Variant var prop dbus.Variant
@@ -213,7 +315,7 @@ func (c *Conn) getProperty(unit string, dbusInterface string, propertyName strin
} }
obj := c.sysconn.Object("org.freedesktop.systemd1", path) obj := c.sysconn.Object("org.freedesktop.systemd1", path)
err = obj.Call("org.freedesktop.DBus.Properties.Get", 0, dbusInterface, propertyName).Store(&prop) err = obj.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, dbusInterface, propertyName).Store(&prop)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -221,21 +323,39 @@ func (c *Conn) getProperty(unit string, dbusInterface string, propertyName strin
return &Property{Name: propertyName, Value: prop}, nil return &Property{Name: propertyName, Value: prop}, nil
} }
// Deprecated: use GetUnitPropertyContext instead
func (c *Conn) GetUnitProperty(unit string, propertyName string) (*Property, error) { func (c *Conn) GetUnitProperty(unit string, propertyName string) (*Property, error) {
return c.getProperty(unit, "org.freedesktop.systemd1.Unit", propertyName) return c.GetUnitPropertyContext(context.Background(), unit, propertyName)
}
// GetUnitPropertyContext same as GetUnitProperty with context
func (c *Conn) GetUnitPropertyContext(ctx context.Context, unit string, propertyName string) (*Property, error) {
return c.getProperty(ctx, unit, "org.freedesktop.systemd1.Unit", propertyName)
} }
// GetServiceProperty returns property for given service name and property name // GetServiceProperty returns property for given service name and property name
// Deprecated: use GetServicePropertyContext instead
func (c *Conn) GetServiceProperty(service string, propertyName string) (*Property, error) { func (c *Conn) GetServiceProperty(service string, propertyName string) (*Property, error) {
return c.getProperty(service, "org.freedesktop.systemd1.Service", propertyName) return c.GetServicePropertyContext(context.Background(), service, propertyName)
}
// GetServicePropertyContext same as GetServiceProperty with context
func (c *Conn) GetServicePropertyContext(ctx context.Context, service string, propertyName string) (*Property, error) {
return c.getProperty(ctx, service, "org.freedesktop.systemd1.Service", propertyName)
} }
// GetUnitTypeProperties returns the extra properties for a unit, specific to the unit type. // GetUnitTypeProperties returns the extra properties for a unit, specific to the unit type.
// Valid values for unitType: Service, Socket, Target, Device, Mount, Automount, Snapshot, Timer, Swap, Path, Slice, Scope // Valid values for unitType: Service, Socket, Target, Device, Mount, Automount, Snapshot, Timer, Swap, Path, Slice, Scope
// return "dbus.Error: Unknown interface" if the unitType is not the correct type of the unit // return "dbus.Error: Unknown interface" if the unitType is not the correct type of the unit
// Deprecated: use GetUnitTypePropertiesContext instead
func (c *Conn) GetUnitTypeProperties(unit string, unitType string) (map[string]interface{}, error) { func (c *Conn) GetUnitTypeProperties(unit string, unitType string) (map[string]interface{}, error) {
return c.GetUnitTypePropertiesContext(context.Background(), unit, unitType)
}
// GetUnitTypePropertiesContext same as GetUnitTypeProperties with context
func (c *Conn) GetUnitTypePropertiesContext(ctx context.Context, unit string, unitType string) (map[string]interface{}, error) {
path := unitPath(unit) path := unitPath(unit)
return c.getProperties(path, "org.freedesktop.systemd1."+unitType) return c.getProperties(ctx, path, "org.freedesktop.systemd1."+unitType)
} }
// SetUnitProperties() may be used to modify certain unit properties at runtime. // SetUnitProperties() may be used to modify certain unit properties at runtime.
@@ -245,12 +365,24 @@ func (c *Conn) GetUnitTypeProperties(unit string, unitType string) (map[string]i
// case the settings only apply until the next reboot. name is the name of the unit // case the settings only apply until the next reboot. name is the name of the unit
// to modify. properties are the settings to set, encoded as an array of property // to modify. properties are the settings to set, encoded as an array of property
// name and value pairs. // name and value pairs.
// Deprecated: use SetUnitPropertiesContext instead
func (c *Conn) SetUnitProperties(name string, runtime bool, properties ...Property) error { func (c *Conn) SetUnitProperties(name string, runtime bool, properties ...Property) error {
return c.sysobj.Call("org.freedesktop.systemd1.Manager.SetUnitProperties", 0, name, runtime, properties).Store() return c.SetUnitPropertiesContext(context.Background(), name, runtime, properties...)
} }
// SetUnitPropertiesContext same as SetUnitProperties with context
func (c *Conn) SetUnitPropertiesContext(ctx context.Context, name string, runtime bool, properties ...Property) error {
return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.SetUnitProperties", 0, name, runtime, properties).Store()
}
// Deprecated: use GetUnitTypePropertyContext instead
func (c *Conn) GetUnitTypeProperty(unit string, unitType string, propertyName string) (*Property, error) { func (c *Conn) GetUnitTypeProperty(unit string, unitType string, propertyName string) (*Property, error) {
return c.getProperty(unit, "org.freedesktop.systemd1."+unitType, propertyName) return c.GetUnitTypePropertyContext(context.Background(), unit, unitType, propertyName)
}
// GetUnitTypePropertyContext same as GetUnitTypeProperty with context
func (c *Conn) GetUnitTypePropertyContext(ctx context.Context, unit string, unitType string, propertyName string) (*Property, error) {
return c.getProperty(ctx, unit, "org.freedesktop.systemd1."+unitType, propertyName)
} }
type UnitStatus struct { type UnitStatus struct {
@@ -299,22 +431,40 @@ func (c *Conn) listUnitsInternal(f storeFunc) ([]UnitStatus, error) {
// be more unit names loaded than actual units behind them. // be more unit names loaded than actual units behind them.
// Also note that a unit is only loaded if it is active and/or enabled. // Also note that a unit is only loaded if it is active and/or enabled.
// Units that are both disabled and inactive will thus not be returned. // Units that are both disabled and inactive will thus not be returned.
// Deprecated: use ListUnitsContext instead
func (c *Conn) ListUnits() ([]UnitStatus, error) { func (c *Conn) ListUnits() ([]UnitStatus, error) {
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnits", 0).Store) return c.ListUnitsContext(context.Background())
}
// ListUnitsContext same as ListUnits with context
func (c *Conn) ListUnitsContext(ctx context.Context) ([]UnitStatus, error) {
return c.listUnitsInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnits", 0).Store)
} }
// ListUnitsFiltered returns an array with units filtered by state. // ListUnitsFiltered returns an array with units filtered by state.
// It takes a list of units' statuses to filter. // It takes a list of units' statuses to filter.
// Deprecated: use ListUnitsFilteredContext instead
func (c *Conn) ListUnitsFiltered(states []string) ([]UnitStatus, error) { func (c *Conn) ListUnitsFiltered(states []string) ([]UnitStatus, error) {
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsFiltered", 0, states).Store) return c.ListUnitsFilteredContext(context.Background(), states)
}
// ListUnitsFilteredContext same as ListUnitsFiltered with context
func (c *Conn) ListUnitsFilteredContext(ctx context.Context, states []string) ([]UnitStatus, error) {
return c.listUnitsInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitsFiltered", 0, states).Store)
} }
// ListUnitsByPatterns returns an array with units. // ListUnitsByPatterns returns an array with units.
// It takes a list of units' statuses and names to filter. // It takes a list of units' statuses and names to filter.
// Note that units may be known by multiple names at the same time, // 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. // and hence there might be more unit names loaded than actual units behind them.
// Deprecated: use ListUnitsByPatternsContext instead
func (c *Conn) ListUnitsByPatterns(states []string, patterns []string) ([]UnitStatus, error) { func (c *Conn) ListUnitsByPatterns(states []string, patterns []string) ([]UnitStatus, error) {
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByPatterns", 0, states, patterns).Store) return c.ListUnitsByPatternsContext(context.Background(), states, patterns)
}
// ListUnitsByPatternsContext same as ListUnitsByPatterns with context
func (c *Conn) ListUnitsByPatternsContext(ctx context.Context, states []string, patterns []string) ([]UnitStatus, error) {
return c.listUnitsInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitsByPatterns", 0, states, patterns).Store)
} }
// ListUnitsByNames returns an array with units. It takes a list of units' // ListUnitsByNames returns an array with units. It takes a list of units'
@@ -322,8 +472,14 @@ func (c *Conn) ListUnitsByPatterns(states []string, patterns []string) ([]UnitSt
// method, this method returns statuses even for inactive or non-existing // method, this method returns statuses even for inactive or non-existing
// units. Input array should contain exact unit names, but not patterns. // units. Input array should contain exact unit names, but not patterns.
// Note: Requires systemd v230 or higher // Note: Requires systemd v230 or higher
// Deprecated: use ListUnitsByNamesContext instead
func (c *Conn) ListUnitsByNames(units []string) ([]UnitStatus, error) { func (c *Conn) ListUnitsByNames(units []string) ([]UnitStatus, error) {
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByNames", 0, units).Store) return c.ListUnitsByNamesContext(context.Background(), units)
}
// ListUnitsByNamesContext same as ListUnitsByNames with context
func (c *Conn) ListUnitsByNamesContext(ctx context.Context, units []string) ([]UnitStatus, error) {
return c.listUnitsInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitsByNames", 0, units).Store)
} }
type UnitFile struct { type UnitFile struct {
@@ -358,13 +514,25 @@ func (c *Conn) listUnitFilesInternal(f storeFunc) ([]UnitFile, error) {
} }
// ListUnitFiles returns an array of all available units on disk. // ListUnitFiles returns an array of all available units on disk.
// Deprecated: use ListUnitFilesContext instead
func (c *Conn) ListUnitFiles() ([]UnitFile, error) { func (c *Conn) ListUnitFiles() ([]UnitFile, error) {
return c.listUnitFilesInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitFiles", 0).Store) return c.ListUnitFilesContext(context.Background())
}
// ListUnitFilesContext same as ListUnitFiles with context
func (c *Conn) ListUnitFilesContext(ctx context.Context) ([]UnitFile, error) {
return c.listUnitFilesInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitFiles", 0).Store)
} }
// ListUnitFilesByPatterns returns an array of all available units on disk matched the patterns. // ListUnitFilesByPatterns returns an array of all available units on disk matched the patterns.
// Deprecated: use ListUnitFilesByPatternsContext instead
func (c *Conn) ListUnitFilesByPatterns(states []string, patterns []string) ([]UnitFile, error) { func (c *Conn) ListUnitFilesByPatterns(states []string, patterns []string) ([]UnitFile, error) {
return c.listUnitFilesInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitFilesByPatterns", 0, states, patterns).Store) return c.ListUnitFilesByPatternsContext(context.Background(), states, patterns)
}
// ListUnitFilesByPatternsContext same as ListUnitFilesByPatterns with context
func (c *Conn) ListUnitFilesByPatternsContext(ctx context.Context, states []string, patterns []string) ([]UnitFile, error) {
return c.listUnitFilesInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitFilesByPatterns", 0, states, patterns).Store)
} }
type LinkUnitFileChange EnableUnitFileChange type LinkUnitFileChange EnableUnitFileChange
@@ -383,9 +551,15 @@ type LinkUnitFileChange EnableUnitFileChange
// structures with three strings: the type of the change (one of symlink // structures with three strings: the type of the change (one of symlink
// or unlink), the file name of the symlink and the destination of the // or unlink), the file name of the symlink and the destination of the
// symlink. // symlink.
// Deprecated: use LinkUnitFilesContext instead
func (c *Conn) LinkUnitFiles(files []string, runtime bool, force bool) ([]LinkUnitFileChange, error) { func (c *Conn) LinkUnitFiles(files []string, runtime bool, force bool) ([]LinkUnitFileChange, error) {
return c.LinkUnitFilesContext(context.Background(), files, runtime, force)
}
// LinkUnitFilesContext same as LinkUnitFiles with context
func (c *Conn) LinkUnitFilesContext(ctx context.Context, files []string, runtime bool, force bool) ([]LinkUnitFileChange, error) {
result := make([][]interface{}, 0) result := make([][]interface{}, 0)
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.LinkUnitFiles", 0, files, runtime, force).Store(&result) err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.LinkUnitFiles", 0, files, runtime, force).Store(&result)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -425,11 +599,17 @@ func (c *Conn) LinkUnitFiles(files []string, runtime bool, force bool) ([]LinkUn
// structures with three strings: the type of the change (one of symlink // structures with three strings: the type of the change (one of symlink
// or unlink), the file name of the symlink and the destination of the // or unlink), the file name of the symlink and the destination of the
// symlink. // symlink.
// Deprecated: use EnableUnitFilesContext instead
func (c *Conn) EnableUnitFiles(files []string, runtime bool, force bool) (bool, []EnableUnitFileChange, error) { func (c *Conn) EnableUnitFiles(files []string, runtime bool, force bool) (bool, []EnableUnitFileChange, error) {
return c.EnableUnitFilesContext(context.Background(), files, runtime, force)
}
// EnableUnitFilesContext same as EnableUnitFiles with context
func (c *Conn) EnableUnitFilesContext(ctx context.Context, files []string, runtime bool, force bool) (bool, []EnableUnitFileChange, error) {
var carries_install_info bool var carries_install_info bool
result := make([][]interface{}, 0) result := make([][]interface{}, 0)
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.EnableUnitFiles", 0, files, runtime, force).Store(&carries_install_info, &result) err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.EnableUnitFiles", 0, files, runtime, force).Store(&carries_install_info, &result)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
@@ -471,9 +651,15 @@ type EnableUnitFileChange struct {
// consists of structures with three strings: the type of the change (one of // consists of structures with three strings: the type of the change (one of
// symlink or unlink), the file name of the symlink and the destination of the // symlink or unlink), the file name of the symlink and the destination of the
// symlink. // symlink.
// Deprecated: use DisableUnitFilesContext instead
func (c *Conn) DisableUnitFiles(files []string, runtime bool) ([]DisableUnitFileChange, error) { func (c *Conn) DisableUnitFiles(files []string, runtime bool) ([]DisableUnitFileChange, error) {
return c.DisableUnitFilesContext(context.Background(), files, runtime)
}
// DisableUnitFilesContext same as DisableUnitFiles with context
func (c *Conn) DisableUnitFilesContext(ctx context.Context, files []string, runtime bool) ([]DisableUnitFileChange, error) {
result := make([][]interface{}, 0) result := make([][]interface{}, 0)
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.DisableUnitFiles", 0, files, runtime).Store(&result) err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.DisableUnitFiles", 0, files, runtime).Store(&result)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -512,9 +698,15 @@ type DisableUnitFileChange struct {
// * runtime to specify whether the unit was enabled for runtime // * runtime to specify whether the unit was enabled for runtime
// only (true, /run/systemd/..), or persistently (false, /etc/systemd/..) // only (true, /run/systemd/..), or persistently (false, /etc/systemd/..)
// * force flag // * force flag
// Deprecated: use MaskUnitFilesContext instead
func (c *Conn) MaskUnitFiles(files []string, runtime bool, force bool) ([]MaskUnitFileChange, error) { func (c *Conn) MaskUnitFiles(files []string, runtime bool, force bool) ([]MaskUnitFileChange, error) {
return c.MaskUnitFilesContext(context.Background(), files, runtime, force)
}
// MaskUnitFilesContext same as MaskUnitFiles with context
func (c *Conn) MaskUnitFilesContext(ctx context.Context, files []string, runtime bool, force bool) ([]MaskUnitFileChange, error) {
result := make([][]interface{}, 0) result := make([][]interface{}, 0)
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.MaskUnitFiles", 0, files, runtime, force).Store(&result) err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.MaskUnitFiles", 0, files, runtime, force).Store(&result)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -552,9 +744,15 @@ type MaskUnitFileChange struct {
// the usual unit search paths) // the usual unit search paths)
// * runtime to specify whether the unit was enabled for runtime // * runtime to specify whether the unit was enabled for runtime
// only (true, /run/systemd/..), or persistently (false, /etc/systemd/..) // only (true, /run/systemd/..), or persistently (false, /etc/systemd/..)
// Deprecated: use UnmaskUnitFilesContext instead
func (c *Conn) UnmaskUnitFiles(files []string, runtime bool) ([]UnmaskUnitFileChange, error) { func (c *Conn) UnmaskUnitFiles(files []string, runtime bool) ([]UnmaskUnitFileChange, error) {
return c.UnmaskUnitFilesContext(context.Background(), files, runtime)
}
// UnmaskUnitFilesContext same as UnmaskUnitFiles with context
func (c *Conn) UnmaskUnitFilesContext(ctx context.Context, files []string, runtime bool) ([]UnmaskUnitFileChange, error) {
result := make([][]interface{}, 0) result := make([][]interface{}, 0)
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.UnmaskUnitFiles", 0, files, runtime).Store(&result) err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.UnmaskUnitFiles", 0, files, runtime).Store(&result)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -586,8 +784,14 @@ type UnmaskUnitFileChange struct {
// Reload instructs systemd to scan for and reload unit files. This is // Reload instructs systemd to scan for and reload unit files. This is
// equivalent to a 'systemctl daemon-reload'. // equivalent to a 'systemctl daemon-reload'.
// Deprecated: use ReloadContext instead
func (c *Conn) Reload() error { func (c *Conn) Reload() error {
return c.sysobj.Call("org.freedesktop.systemd1.Manager.Reload", 0).Store() return c.ReloadContext(context.Background())
}
// ReloadContext same as Reload with context
func (c *Conn) ReloadContext(ctx context.Context) error {
return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.Reload", 0).Store()
} }
func unitPath(name string) dbus.ObjectPath { func unitPath(name string) dbus.ObjectPath {
@@ -598,3 +802,48 @@ func unitPath(name string) dbus.ObjectPath {
func unitName(dpath dbus.ObjectPath) string { func unitName(dpath dbus.ObjectPath) string {
return pathBusUnescape(path.Base(string(dpath))) return pathBusUnescape(path.Base(string(dpath)))
} }
// Currently queued job definition
type JobStatus struct {
Id uint32 // The numeric job id
Unit string // The primary unit name for this job
JobType string // The job type as string
Status string // The job state as string
JobPath dbus.ObjectPath // The job object path
UnitPath dbus.ObjectPath // The unit object path
}
// ListJobs returns an array with all currently queued jobs
// Deprecated: use ListJobsContext instead
func (c *Conn) ListJobs() ([]JobStatus, error) {
return c.ListJobsContext(context.Background())
}
// ListJobsContext same as ListJobs with context
func (c *Conn) ListJobsContext(ctx context.Context) ([]JobStatus, error) {
return c.listJobsInternal(ctx)
}
func (c *Conn) listJobsInternal(ctx context.Context) ([]JobStatus, error) {
result := make([][]interface{}, 0)
if err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListJobs", 0).Store(&result); err != nil {
return nil, err
}
resultInterface := make([]interface{}, len(result))
for i := range result {
resultInterface[i] = result[i]
}
status := make([]JobStatus, len(result))
statusInterface := make([]interface{}, len(status))
for i := range status {
statusInterface[i] = &status[i]
}
if err := dbus.Store(resultInterface, statusInterface...); err != nil {
return nil, err
}
return status, nil
}
-50
View File
@@ -1,50 +0,0 @@
dist: bionic
language: go
go_import_path: github.com/godbus/dbus
go:
- 1.11.x
- 1.12.x
- 1.13.x
- tip
matrix:
fast_finish: true
allow_failures:
- go: tip
addons:
apt:
packages:
- dbus
- dbus-x11
before_install:
- export GO111MODULE=on
script:
- go test -v -race -mod=readonly ./... # Run all the tests with the race detector enabled
- go vet ./... # go vet is the official Go static analyzer
jobs:
include:
# The build matrix doesn't cover build stages, so manually expand
# the jobs with anchors
- &multiarch
stage: "Multiarch Test"
go: 1.11.x
env: TARGETS="386 arm arm64 ppc64le"
before_install:
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
script:
- |
set -e
for target in $TARGETS; do
printf "\e[1mRunning test suite under ${target}.\e[0m\n"
GOARCH="$target" go test -v ./...
printf "\n\n"
done
- <<: *multiarch
go: 1.12.x
- <<: *multiarch
go: 1.13.x
+3 -1
View File
@@ -1,4 +1,4 @@
[![Build Status](https://travis-ci.org/godbus/dbus.svg?branch=master)](https://travis-ci.org/godbus/dbus) ![Build Status](https://github.com/godbus/dbus/workflows/Go/badge.svg)
dbus dbus
---- ----
@@ -32,6 +32,8 @@ gives a short overview over the basic usage.
#### Projects using godbus #### Projects using godbus
- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library. - [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
- [go-bluetooth](https://github.com/muka/go-bluetooth) provides a bluetooth client over bluez dbus API. - [go-bluetooth](https://github.com/muka/go-bluetooth) provides a bluetooth client over bluez dbus API.
- [playerbm](https://github.com/altdesktop/playerbm) a bookmark utility for media players.
- [iwd](https://github.com/shibumi/iwd) go bindings for the internet wireless daemon "iwd".
Please note that the API is considered unstable for now and may change without Please note that the API is considered unstable for now and may change without
further notice. further notice.
+1 -1
View File
@@ -37,7 +37,7 @@ const (
// Auth defines the behaviour of an authentication mechanism. // Auth defines the behaviour of an authentication mechanism.
type Auth interface { type Auth interface {
// Return the name of the mechnism, the argument to the first AUTH command // Return the name of the mechanism, the argument to the first AUTH command
// and the next status. // and the next status.
FirstData() (name, resp []byte, status AuthStatus) FirstData() (name, resp []byte, status AuthStatus)
+9
View File
@@ -24,6 +24,15 @@ type Call struct {
// Holds the response once the call is done. // Holds the response once the call is done.
Body []interface{} Body []interface{}
// ResponseSequence stores the sequence number of the DBus message containing
// the call response (or error). This can be compared to the sequence number
// of other call responses and signals on this connection to determine their
// relative ordering on the underlying DBus connection.
// For errors, ResponseSequence is populated only if the error came from a
// DBusMessage that was received or if there was an error receiving. In case of
// failure to make the call, ResponseSequence will be NoSequence.
ResponseSequence Sequence
// tracks context and canceler // tracks context and canceler
ctx context.Context ctx context.Context
ctxCanceler context.CancelFunc ctxCanceler context.CancelFunc
+103 -56
View File
@@ -45,6 +45,7 @@ type Conn struct {
serialGen SerialGenerator serialGen SerialGenerator
inInt Interceptor inInt Interceptor
outInt Interceptor outInt Interceptor
auth []Auth
names *nameTracker names *nameTracker
calls *callTracker calls *callTracker
@@ -59,7 +60,8 @@ type Conn struct {
func SessionBus() (conn *Conn, err error) { func SessionBus() (conn *Conn, err error) {
sessionBusLck.Lock() sessionBusLck.Lock()
defer sessionBusLck.Unlock() defer sessionBusLck.Unlock()
if sessionBus != nil { if sessionBus != nil &&
sessionBus.Connected() {
return sessionBus, nil return sessionBus, nil
} }
defer func() { defer func() {
@@ -67,19 +69,7 @@ func SessionBus() (conn *Conn, err error) {
sessionBus = conn sessionBus = conn
} }
}() }()
conn, err = SessionBusPrivate() conn, err = ConnectSessionBus()
if err != nil {
return
}
if err = conn.Auth(nil); err != nil {
conn.Close()
conn = nil
return
}
if err = conn.Hello(); err != nil {
conn.Close()
conn = nil
}
return return
} }
@@ -116,7 +106,8 @@ func SessionBusPrivateHandler(handler Handler, signalHandler SignalHandler) (*Co
func SystemBus() (conn *Conn, err error) { func SystemBus() (conn *Conn, err error) {
systemBusLck.Lock() systemBusLck.Lock()
defer systemBusLck.Unlock() defer systemBusLck.Unlock()
if systemBus != nil { if systemBus != nil &&
systemBus.Connected() {
return systemBus, nil return systemBus, nil
} }
defer func() { defer func() {
@@ -124,20 +115,42 @@ func SystemBus() (conn *Conn, err error) {
systemBus = conn systemBus = conn
} }
}() }()
conn, err = SystemBusPrivate() conn, err = ConnectSystemBus()
return
}
// ConnectSessionBus connects to the session bus.
func ConnectSessionBus(opts ...ConnOption) (*Conn, error) {
address, err := getSessionBusAddress()
if err != nil { if err != nil {
return return nil, err
} }
if err = conn.Auth(nil); err != nil { return Connect(address, opts...)
conn.Close() }
conn = nil
return // ConnectSystemBus connects to the system bus.
func ConnectSystemBus(opts ...ConnOption) (*Conn, error) {
return Connect(getSystemBusPlatformAddress(), opts...)
}
// Connect connects to the given address.
//
// Returned connection is ready to use and doesn't require calling
// Auth and Hello methods to make it usable.
func Connect(address string, opts ...ConnOption) (*Conn, error) {
conn, err := Dial(address, opts...)
if err != nil {
return nil, err
}
if err = conn.Auth(conn.auth); err != nil {
_ = conn.Close()
return nil, err
} }
if err = conn.Hello(); err != nil { if err = conn.Hello(); err != nil {
conn.Close() _ = conn.Close()
conn = nil return nil, err
} }
return return conn, nil
} }
// SystemBusPrivate returns a new private connection to the system bus. // SystemBusPrivate returns a new private connection to the system bus.
@@ -197,6 +210,14 @@ func WithSerialGenerator(gen SerialGenerator) ConnOption {
} }
} }
// WithAuth sets authentication methods for the auth conversation.
func WithAuth(methods ...Auth) ConnOption {
return func(conn *Conn) error {
conn.auth = methods
return nil
}
}
// Interceptor intercepts incoming and outgoing messages. // Interceptor intercepts incoming and outgoing messages.
type Interceptor func(msg *Message) type Interceptor func(msg *Message)
@@ -309,6 +330,11 @@ func (conn *Conn) Context() context.Context {
return conn.ctx return conn.ctx
} }
// Connected returns whether conn is connected
func (conn *Conn) Connected() bool {
return conn.ctx.Err() == nil
}
// Eavesdrop causes conn to send all incoming messages to the given channel // Eavesdrop causes conn to send all incoming messages to the given channel
// without further processing. Method replies, errors and signals will not be // without further processing. Method replies, errors and signals will not be
// sent to the appropriate channels and method calls will not be handled. If nil // sent to the appropriate channels and method calls will not be handled. If nil
@@ -342,8 +368,9 @@ func (conn *Conn) Hello() error {
} }
// inWorker runs in an own goroutine, reading incoming messages from the // inWorker runs in an own goroutine, reading incoming messages from the
// transport and dispatching them appropiately. // transport and dispatching them appropriately.
func (conn *Conn) inWorker() { func (conn *Conn) inWorker() {
sequenceGen := newSequenceGenerator()
for { for {
msg, err := conn.ReadMessage() msg, err := conn.ReadMessage()
if err != nil { if err != nil {
@@ -352,7 +379,7 @@ func (conn *Conn) inWorker() {
// anything but to shut down all stuff and returns errors to all // anything but to shut down all stuff and returns errors to all
// pending replies. // pending replies.
conn.Close() conn.Close()
conn.calls.finalizeAllWithError(err) conn.calls.finalizeAllWithError(sequenceGen, err)
return return
} }
// invalid messages are ignored // invalid messages are ignored
@@ -381,13 +408,14 @@ func (conn *Conn) inWorker() {
if conn.inInt != nil { if conn.inInt != nil {
conn.inInt(msg) conn.inInt(msg)
} }
sequence := sequenceGen.next()
switch msg.Type { switch msg.Type {
case TypeError: case TypeError:
conn.serialGen.RetireSerial(conn.calls.handleDBusError(msg)) conn.serialGen.RetireSerial(conn.calls.handleDBusError(sequence, msg))
case TypeMethodReply: case TypeMethodReply:
conn.serialGen.RetireSerial(conn.calls.handleReply(msg)) conn.serialGen.RetireSerial(conn.calls.handleReply(sequence, msg))
case TypeSignal: case TypeSignal:
conn.handleSignal(msg) conn.handleSignal(sequence, msg)
case TypeMethodCall: case TypeMethodCall:
go conn.handleCall(msg) go conn.handleCall(msg)
} }
@@ -395,7 +423,7 @@ func (conn *Conn) inWorker() {
} }
} }
func (conn *Conn) handleSignal(msg *Message) { func (conn *Conn) handleSignal(sequence Sequence, msg *Message) {
iface := msg.Headers[FieldInterface].value.(string) iface := msg.Headers[FieldInterface].value.(string)
member := msg.Headers[FieldMember].value.(string) member := msg.Headers[FieldMember].value.(string)
// as per http://dbus.freedesktop.org/doc/dbus-specification.html , // as per http://dbus.freedesktop.org/doc/dbus-specification.html ,
@@ -421,10 +449,11 @@ func (conn *Conn) handleSignal(msg *Message) {
} }
} }
signal := &Signal{ signal := &Signal{
Sender: sender, Sender: sender,
Path: msg.Headers[FieldPath].value.(ObjectPath), Path: msg.Headers[FieldPath].value.(ObjectPath),
Name: iface + "." + member, Name: iface + "." + member,
Body: msg.Body, Body: msg.Body,
Sequence: sequence,
} }
conn.signalHandler.DeliverSignal(iface, member, signal) conn.signalHandler.DeliverSignal(iface, member, signal)
} }
@@ -442,6 +471,9 @@ func (conn *Conn) Object(dest string, path ObjectPath) BusObject {
} }
func (conn *Conn) sendMessageAndIfClosed(msg *Message, ifClosed func()) { func (conn *Conn) sendMessageAndIfClosed(msg *Message, ifClosed func()) {
if msg.serial == 0 {
msg.serial = conn.getSerial()
}
if conn.outInt != nil { if conn.outInt != nil {
conn.outInt(msg) conn.outInt(msg)
} }
@@ -473,16 +505,16 @@ func (conn *Conn) send(ctx context.Context, msg *Message, ch chan *Call) *Call {
if ctx == nil { if ctx == nil {
panic("nil context") panic("nil context")
} }
if ch == nil {
ch = make(chan *Call, 1)
} else if cap(ch) == 0 {
panic("dbus: unbuffered channel passed to (*Conn).Send")
}
var call *Call var call *Call
ctx, canceler := context.WithCancel(ctx) ctx, canceler := context.WithCancel(ctx)
msg.serial = conn.getSerial() msg.serial = conn.getSerial()
if msg.Type == TypeMethodCall && msg.Flags&FlagNoReplyExpected == 0 { if msg.Type == TypeMethodCall && msg.Flags&FlagNoReplyExpected == 0 {
if ch == nil {
ch = make(chan *Call, 5)
} else if cap(ch) == 0 {
panic("dbus: unbuffered channel passed to (*Conn).Send")
}
call = new(Call) call = new(Call)
call.Destination, _ = msg.Headers[FieldDestination].value.(string) call.Destination, _ = msg.Headers[FieldDestination].value.(string)
call.Path, _ = msg.Headers[FieldPath].value.(ObjectPath) call.Path, _ = msg.Headers[FieldPath].value.(ObjectPath)
@@ -504,7 +536,8 @@ func (conn *Conn) send(ctx context.Context, msg *Message, ch chan *Call) *Call {
}) })
} else { } else {
canceler() canceler()
call = &Call{Err: nil} call = &Call{Err: nil, Done: ch}
ch <- call
conn.sendMessageAndIfClosed(msg, func() { conn.sendMessageAndIfClosed(msg, func() {
call = &Call{Err: ErrClosed} call = &Call{Err: ErrClosed}
}) })
@@ -529,7 +562,6 @@ func (conn *Conn) sendError(err error, dest string, serial uint32) {
} }
msg := new(Message) msg := new(Message)
msg.Type = TypeError msg.Type = TypeError
msg.serial = conn.getSerial()
msg.Headers = make(map[HeaderField]Variant) msg.Headers = make(map[HeaderField]Variant)
if dest != "" { if dest != "" {
msg.Headers[FieldDestination] = MakeVariant(dest) msg.Headers[FieldDestination] = MakeVariant(dest)
@@ -548,7 +580,6 @@ func (conn *Conn) sendError(err error, dest string, serial uint32) {
func (conn *Conn) sendReply(dest string, serial uint32, values ...interface{}) { func (conn *Conn) sendReply(dest string, serial uint32, values ...interface{}) {
msg := new(Message) msg := new(Message)
msg.Type = TypeMethodReply msg.Type = TypeMethodReply
msg.serial = conn.getSerial()
msg.Headers = make(map[HeaderField]Variant) msg.Headers = make(map[HeaderField]Variant)
if dest != "" { if dest != "" {
msg.Headers[FieldDestination] = MakeVariant(dest) msg.Headers[FieldDestination] = MakeVariant(dest)
@@ -564,8 +595,14 @@ func (conn *Conn) sendReply(dest string, serial uint32, values ...interface{}) {
// AddMatchSignal registers the given match rule to receive broadcast // AddMatchSignal registers the given match rule to receive broadcast
// signals based on their contents. // signals based on their contents.
func (conn *Conn) AddMatchSignal(options ...MatchOption) error { func (conn *Conn) AddMatchSignal(options ...MatchOption) error {
return conn.AddMatchSignalContext(context.Background(), options...)
}
// AddMatchSignalContext acts like AddMatchSignal but takes a context.
func (conn *Conn) AddMatchSignalContext(ctx context.Context, options ...MatchOption) error {
options = append([]MatchOption{withMatchType("signal")}, options...) options = append([]MatchOption{withMatchType("signal")}, options...)
return conn.busObj.Call( return conn.busObj.CallWithContext(
ctx,
"org.freedesktop.DBus.AddMatch", 0, "org.freedesktop.DBus.AddMatch", 0,
formatMatchOptions(options), formatMatchOptions(options),
).Store() ).Store()
@@ -573,8 +610,14 @@ func (conn *Conn) AddMatchSignal(options ...MatchOption) error {
// RemoveMatchSignal removes the first rule that matches previously registered with AddMatchSignal. // RemoveMatchSignal removes the first rule that matches previously registered with AddMatchSignal.
func (conn *Conn) RemoveMatchSignal(options ...MatchOption) error { func (conn *Conn) RemoveMatchSignal(options ...MatchOption) error {
return conn.RemoveMatchSignalContext(context.Background(), options...)
}
// RemoveMatchSignalContext acts like RemoveMatchSignal but takes a context.
func (conn *Conn) RemoveMatchSignalContext(ctx context.Context, options ...MatchOption) error {
options = append([]MatchOption{withMatchType("signal")}, options...) options = append([]MatchOption{withMatchType("signal")}, options...)
return conn.busObj.Call( return conn.busObj.CallWithContext(
ctx,
"org.freedesktop.DBus.RemoveMatch", 0, "org.freedesktop.DBus.RemoveMatch", 0,
formatMatchOptions(options), formatMatchOptions(options),
).Store() ).Store()
@@ -639,10 +682,11 @@ func (e Error) Error() string {
// Signal represents a D-Bus message of type Signal. The name member is given in // Signal represents a D-Bus message of type Signal. The name member is given in
// "interface.member" notation, e.g. org.freedesktop.D-Bus.NameLost. // "interface.member" notation, e.g. org.freedesktop.D-Bus.NameLost.
type Signal struct { type Signal struct {
Sender string Sender string
Path ObjectPath Path ObjectPath
Name string Name string
Body []interface{} Body []interface{}
Sequence Sequence
} }
// transport is a D-Bus transport. // transport is a D-Bus transport.
@@ -825,25 +869,25 @@ func (tracker *callTracker) track(sn uint32, call *Call) {
tracker.lck.Unlock() tracker.lck.Unlock()
} }
func (tracker *callTracker) handleReply(msg *Message) uint32 { func (tracker *callTracker) handleReply(sequence Sequence, msg *Message) uint32 {
serial := msg.Headers[FieldReplySerial].value.(uint32) serial := msg.Headers[FieldReplySerial].value.(uint32)
tracker.lck.RLock() tracker.lck.RLock()
_, ok := tracker.calls[serial] _, ok := tracker.calls[serial]
tracker.lck.RUnlock() tracker.lck.RUnlock()
if ok { if ok {
tracker.finalizeWithBody(serial, msg.Body) tracker.finalizeWithBody(serial, sequence, msg.Body)
} }
return serial return serial
} }
func (tracker *callTracker) handleDBusError(msg *Message) uint32 { func (tracker *callTracker) handleDBusError(sequence Sequence, msg *Message) uint32 {
serial := msg.Headers[FieldReplySerial].value.(uint32) serial := msg.Headers[FieldReplySerial].value.(uint32)
tracker.lck.RLock() tracker.lck.RLock()
_, ok := tracker.calls[serial] _, ok := tracker.calls[serial]
tracker.lck.RUnlock() tracker.lck.RUnlock()
if ok { if ok {
name, _ := msg.Headers[FieldErrorName].value.(string) name, _ := msg.Headers[FieldErrorName].value.(string)
tracker.finalizeWithError(serial, Error{name, msg.Body}) tracker.finalizeWithError(serial, sequence, Error{name, msg.Body})
} }
return serial return serial
} }
@@ -856,7 +900,7 @@ func (tracker *callTracker) handleSendError(msg *Message, err error) {
_, ok := tracker.calls[msg.serial] _, ok := tracker.calls[msg.serial]
tracker.lck.RUnlock() tracker.lck.RUnlock()
if ok { if ok {
tracker.finalizeWithError(msg.serial, err) tracker.finalizeWithError(msg.serial, NoSequence, err)
} }
} }
@@ -871,7 +915,7 @@ func (tracker *callTracker) finalize(sn uint32) {
} }
} }
func (tracker *callTracker) finalizeWithBody(sn uint32, body []interface{}) { func (tracker *callTracker) finalizeWithBody(sn uint32, sequence Sequence, body []interface{}) {
tracker.lck.Lock() tracker.lck.Lock()
c, ok := tracker.calls[sn] c, ok := tracker.calls[sn]
if ok { if ok {
@@ -880,11 +924,12 @@ func (tracker *callTracker) finalizeWithBody(sn uint32, body []interface{}) {
tracker.lck.Unlock() tracker.lck.Unlock()
if ok { if ok {
c.Body = body c.Body = body
c.ResponseSequence = sequence
c.done() c.done()
} }
} }
func (tracker *callTracker) finalizeWithError(sn uint32, err error) { func (tracker *callTracker) finalizeWithError(sn uint32, sequence Sequence, err error) {
tracker.lck.Lock() tracker.lck.Lock()
c, ok := tracker.calls[sn] c, ok := tracker.calls[sn]
if ok { if ok {
@@ -893,11 +938,12 @@ func (tracker *callTracker) finalizeWithError(sn uint32, err error) {
tracker.lck.Unlock() tracker.lck.Unlock()
if ok { if ok {
c.Err = err c.Err = err
c.ResponseSequence = sequence
c.done() c.done()
} }
} }
func (tracker *callTracker) finalizeAllWithError(err error) { func (tracker *callTracker) finalizeAllWithError(sequenceGen *sequenceGenerator, err error) {
tracker.lck.Lock() tracker.lck.Lock()
closedCalls := make([]*Call, 0, len(tracker.calls)) closedCalls := make([]*Call, 0, len(tracker.calls))
for sn := range tracker.calls { for sn := range tracker.calls {
@@ -907,6 +953,7 @@ func (tracker *callTracker) finalizeAllWithError(err error) {
tracker.lck.Unlock() tracker.lck.Unlock()
for _, call := range closedCalls { for _, call := range closedCalls {
call.Err = err call.Err = err
call.ResponseSequence = sequenceGen.next()
call.done() call.done()
} }
} }
+4
View File
@@ -28,6 +28,7 @@ var (
interfaceType = reflect.TypeOf((*interface{})(nil)).Elem() interfaceType = reflect.TypeOf((*interface{})(nil)).Elem()
unixFDType = reflect.TypeOf(UnixFD(0)) unixFDType = reflect.TypeOf(UnixFD(0))
unixFDIndexType = reflect.TypeOf(UnixFDIndex(0)) unixFDIndexType = reflect.TypeOf(UnixFDIndex(0))
errType = reflect.TypeOf((*error)(nil)).Elem()
) )
// An InvalidTypeError signals that a value which cannot be represented in the // An InvalidTypeError signals that a value which cannot be represented in the
@@ -63,6 +64,9 @@ func storeInterfaces(src, dest interface{}) error {
func store(dest, src reflect.Value) error { func store(dest, src reflect.Value) error {
if dest.Kind() == reflect.Ptr { if dest.Kind() == reflect.Ptr {
if dest.IsNil() {
dest.Set(reflect.New(dest.Type().Elem()))
}
return store(dest.Elem(), src) return store(dest.Elem(), src)
} }
switch src.Kind() { switch src.Kind() {
+18 -4
View File
@@ -126,14 +126,28 @@ func (m exportedMethod) Call(args ...interface{}) ([]interface{}, error) {
} }
ret := m.Value.Call(params) ret := m.Value.Call(params)
var err error
err := ret[t.NumOut()-1].Interface().(*Error) nilErr := false // The reflection will find almost-nils, let's only pass back clean ones!
ret = ret[:t.NumOut()-1] if t.NumOut() > 0 {
if e, ok := ret[t.NumOut()-1].Interface().(*Error); ok { // godbus *Error
nilErr = ret[t.NumOut()-1].IsNil()
ret = ret[:t.NumOut()-1]
err = e
} else if ret[t.NumOut()-1].Type().Implements(errType) { // Go error
i := ret[t.NumOut()-1].Interface()
if i == nil {
nilErr = ret[t.NumOut()-1].IsNil()
} else {
err = i.(error)
}
ret = ret[:t.NumOut()-1]
}
}
out := make([]interface{}, len(ret)) out := make([]interface{}, len(ret))
for i, val := range ret { for i, val := range ret {
out[i] = val.Interface() out[i] = val.Interface()
} }
if err == nil { if nilErr || err == nil {
//concrete type to interface nil is a special case //concrete type to interface nil is a special case
return out, nil return out, nil
} }
+45 -16
View File
@@ -69,6 +69,22 @@ func getMethods(in interface{}, mapping map[string]string) map[string]reflect.Va
return methods return methods
} }
func getAllMethods(in interface{}, mapping map[string]string) map[string]reflect.Value {
if in == nil {
return nil
}
methods := make(map[string]reflect.Value)
val := reflect.ValueOf(in)
typ := val.Type()
for i := 0; i < typ.NumMethod(); i++ {
methtype := typ.Method(i)
method := val.Method(i)
// map names while building table
methods[computeMethodName(methtype.Name, mapping)] = method
}
return methods
}
func standardMethodArgumentDecode(m Method, sender string, msg *Message, body []interface{}) ([]interface{}, error) { func standardMethodArgumentDecode(m Method, sender string, msg *Message, body []interface{}) ([]interface{}, error) {
pointers := make([]interface{}, m.NumArguments()) pointers := make([]interface{}, m.NumArguments())
decode := make([]interface{}, 0, len(body)) decode := make([]interface{}, 0, len(body))
@@ -159,7 +175,6 @@ func (conn *Conn) handleCall(msg *Message) {
if msg.Flags&FlagNoReplyExpected == 0 { if msg.Flags&FlagNoReplyExpected == 0 {
reply := new(Message) reply := new(Message)
reply.Type = TypeMethodReply reply.Type = TypeMethodReply
reply.serial = conn.getSerial()
reply.Headers = make(map[HeaderField]Variant) reply.Headers = make(map[HeaderField]Variant)
if hasSender { if hasSender {
reply.Headers[FieldDestination] = msg.Headers[FieldSender] reply.Headers[FieldDestination] = msg.Headers[FieldSender]
@@ -195,7 +210,6 @@ func (conn *Conn) Emit(path ObjectPath, name string, values ...interface{}) erro
} }
msg := new(Message) msg := new(Message)
msg.Type = TypeSignal msg.Type = TypeSignal
msg.serial = conn.getSerial()
msg.Headers = make(map[HeaderField]Variant) msg.Headers = make(map[HeaderField]Variant)
msg.Headers[FieldInterface] = MakeVariant(iface) msg.Headers[FieldInterface] = MakeVariant(iface)
msg.Headers[FieldMember] = MakeVariant(member) msg.Headers[FieldMember] = MakeVariant(member)
@@ -247,6 +261,18 @@ func (conn *Conn) Export(v interface{}, path ObjectPath, iface string) error {
return conn.ExportWithMap(v, nil, path, iface) return conn.ExportWithMap(v, nil, path, iface)
} }
// ExportAll registers all exported methods defined by the given object on
// the message bus.
//
// Unlike Export there is no requirement to have the last parameter as type
// *Error. If you want to be able to return error then you can append an error
// type parameter to your method signature. If the error returned is not nil,
// it is sent back to the caller as an error. Otherwise, a method reply is
// sent with the other return values as its body.
func (conn *Conn) ExportAll(v interface{}, path ObjectPath, iface string) error {
return conn.export(getAllMethods(v, nil), path, iface, false)
}
// ExportWithMap works exactly like Export but provides the ability to remap // ExportWithMap works exactly like Export but provides the ability to remap
// method names (e.g. export a lower-case method). // method names (e.g. export a lower-case method).
// //
@@ -299,19 +325,22 @@ func (conn *Conn) ExportSubtreeMethodTable(methods map[string]interface{}, path
} }
func (conn *Conn) exportMethodTable(methods map[string]interface{}, path ObjectPath, iface string, includeSubtree bool) error { func (conn *Conn) exportMethodTable(methods map[string]interface{}, path ObjectPath, iface string, includeSubtree bool) error {
out := make(map[string]reflect.Value) var out map[string]reflect.Value
for name, method := range methods { if methods != nil {
rval := reflect.ValueOf(method) out = make(map[string]reflect.Value)
if rval.Kind() != reflect.Func { for name, method := range methods {
continue rval := reflect.ValueOf(method)
if rval.Kind() != reflect.Func {
continue
}
t := rval.Type()
// only track valid methods must return *Error as last arg
if t.NumOut() == 0 ||
t.Out(t.NumOut()-1) != reflect.TypeOf(&ErrMsgInvalidArg) {
continue
}
out[name] = rval
} }
t := rval.Type()
// only track valid methods must return *Error as last arg
if t.NumOut() == 0 ||
t.Out(t.NumOut()-1) != reflect.TypeOf(&ErrMsgInvalidArg) {
continue
}
out[name] = rval
} }
return conn.export(out, path, iface, includeSubtree) return conn.export(out, path, iface, includeSubtree)
} }
@@ -327,12 +356,12 @@ func (conn *Conn) unexport(h *defaultHandler, path ObjectPath, iface string) err
return nil return nil
} }
// exportWithMap is the worker function for all exports/registrations. // export is the worker function for all exports/registrations.
func (conn *Conn) export(methods map[string]reflect.Value, path ObjectPath, iface string, includeSubtree bool) error { func (conn *Conn) export(methods map[string]reflect.Value, path ObjectPath, iface string, includeSubtree bool) error {
h, ok := conn.handler.(*defaultHandler) h, ok := conn.handler.(*defaultHandler)
if !ok { if !ok {
return fmt.Errorf( return fmt.Errorf(
`dbus: export only allowed on the default hander handler have %T"`, `dbus: export only allowed on the default handler. Received: %T"`,
conn.handler) conn.handler)
} }
+27
View File
@@ -1,6 +1,7 @@
package dbus package dbus
import ( import (
"strconv"
"strings" "strings"
) )
@@ -60,3 +61,29 @@ func WithMatchPathNamespace(namespace ObjectPath) MatchOption {
func WithMatchDestination(destination string) MatchOption { func WithMatchDestination(destination string) MatchOption {
return WithMatchOption("destination", destination) return WithMatchOption("destination", destination)
} }
// WithMatchArg sets argN match option, range of N is 0 to 63.
func WithMatchArg(argIdx int, value string) MatchOption {
if argIdx < 0 || argIdx > 63 {
panic("range of argument index is 0 to 63")
}
return WithMatchOption("arg"+strconv.Itoa(argIdx), value)
}
// WithMatchArgPath sets argN path match option, range of N is 0 to 63.
func WithMatchArgPath(argIdx int, path string) MatchOption {
if argIdx < 0 || argIdx > 63 {
panic("range of argument index is 0 to 63")
}
return WithMatchOption("arg"+strconv.Itoa(argIdx)+"path", path)
}
// WithMatchArg0Namespace sets arg0namespace match option.
func WithMatchArg0Namespace(arg0Namespace string) MatchOption {
return WithMatchOption("arg0namespace", arg0Namespace)
}
// WithMatchEavesdrop sets eavesdrop match option.
func WithMatchEavesdrop(eavesdrop bool) MatchOption {
return WithMatchOption("eavesdrop", strconv.FormatBool(eavesdrop))
}
+14 -51
View File
@@ -16,6 +16,7 @@ type BusObject interface {
AddMatchSignal(iface, member string, options ...MatchOption) *Call AddMatchSignal(iface, member string, options ...MatchOption) *Call
RemoveMatchSignal(iface, member string, options ...MatchOption) *Call RemoveMatchSignal(iface, member string, options ...MatchOption) *Call
GetProperty(p string) (Variant, error) GetProperty(p string) (Variant, error)
StoreProperty(p string, value interface{}) error
SetProperty(p string, v interface{}) error SetProperty(p string, v interface{}) error
Destination() string Destination() string
Path() ObjectPath Path() ObjectPath
@@ -109,7 +110,6 @@ func (o *Object) createCall(ctx context.Context, method string, flags Flags, ch
method = method[i+1:] method = method[i+1:]
msg := new(Message) msg := new(Message)
msg.Type = TypeMethodCall msg.Type = TypeMethodCall
msg.serial = o.conn.getSerial()
msg.Flags = flags & (FlagNoAutoStart | FlagNoReplyExpected) msg.Flags = flags & (FlagNoAutoStart | FlagNoReplyExpected)
msg.Headers = make(map[HeaderField]Variant) msg.Headers = make(map[HeaderField]Variant)
msg.Headers[FieldPath] = MakeVariant(o.path) msg.Headers[FieldPath] = MakeVariant(o.path)
@@ -122,68 +122,31 @@ func (o *Object) createCall(ctx context.Context, method string, flags Flags, ch
if len(args) > 0 { if len(args) > 0 {
msg.Headers[FieldSignature] = MakeVariant(SignatureOf(args...)) msg.Headers[FieldSignature] = MakeVariant(SignatureOf(args...))
} }
if msg.Flags&FlagNoReplyExpected == 0 { return o.conn.SendWithContext(ctx, msg, ch)
if ch == nil {
ch = make(chan *Call, 1)
} else if cap(ch) == 0 {
panic("dbus: unbuffered channel passed to (*Object).Go")
}
ctx, cancel := context.WithCancel(ctx)
call := &Call{
Destination: o.dest,
Path: o.path,
Method: method,
Args: args,
Done: ch,
ctxCanceler: cancel,
ctx: ctx,
}
o.conn.calls.track(msg.serial, call)
o.conn.sendMessageAndIfClosed(msg, func() {
o.conn.calls.handleSendError(msg, ErrClosed)
cancel()
})
go func() {
<-ctx.Done()
o.conn.calls.handleSendError(msg, ctx.Err())
}()
return call
}
done := make(chan *Call, 1)
call := &Call{
Err: nil,
Done: done,
}
defer func() {
call.Done <- call
close(done)
}()
o.conn.sendMessageAndIfClosed(msg, func() {
call.Err = ErrClosed
})
return call
} }
// GetProperty calls org.freedesktop.DBus.Properties.Get on the given // GetProperty calls org.freedesktop.DBus.Properties.Get on the given
// object. The property name must be given in interface.member notation. // object. The property name must be given in interface.member notation.
func (o *Object) GetProperty(p string) (Variant, error) { func (o *Object) GetProperty(p string) (Variant, error) {
var result Variant
err := o.StoreProperty(p, &result)
return result, err
}
// StoreProperty calls org.freedesktop.DBus.Properties.Get on the given
// object. The property name must be given in interface.member notation.
// It stores the returned property into the provided value.
func (o *Object) StoreProperty(p string, value interface{}) error {
idx := strings.LastIndex(p, ".") idx := strings.LastIndex(p, ".")
if idx == -1 || idx+1 == len(p) { if idx == -1 || idx+1 == len(p) {
return Variant{}, errors.New("dbus: invalid property " + p) return errors.New("dbus: invalid property " + p)
} }
iface := p[:idx] iface := p[:idx]
prop := p[idx+1:] prop := p[idx+1:]
result := Variant{} return o.Call("org.freedesktop.DBus.Properties.Get", 0, iface, prop).
err := o.Call("org.freedesktop.DBus.Properties.Get", 0, iface, prop).Store(&result) Store(value)
if err != nil {
return Variant{}, err
}
return result, nil
} }
// SetProperty calls org.freedesktop.DBus.Properties.Set on the given // SetProperty calls org.freedesktop.DBus.Properties.Set on the given
+24
View File
@@ -0,0 +1,24 @@
package dbus
// Sequence represents the value of a monotonically increasing counter.
type Sequence uint64
const (
// NoSequence indicates the absence of a sequence value.
NoSequence Sequence = 0
)
// sequenceGenerator represents a monotonically increasing counter.
type sequenceGenerator struct {
nextSequence Sequence
}
func (generator *sequenceGenerator) next() Sequence {
result := generator.nextSequence
generator.nextSequence++
return result
}
func newSequenceGenerator() *sequenceGenerator {
return &sequenceGenerator{nextSequence: 1}
}
+125
View File
@@ -0,0 +1,125 @@
package dbus
import (
"sync"
)
// NewSequentialSignalHandler returns an instance of a new
// signal handler that guarantees sequential processing of signals. It is a
// guarantee of this signal handler that signals will be written to
// channels in the order they are received on the DBus connection.
func NewSequentialSignalHandler() SignalHandler {
return &sequentialSignalHandler{}
}
type sequentialSignalHandler struct {
mu sync.RWMutex
closed bool
signals []*sequentialSignalChannelData
}
func (sh *sequentialSignalHandler) DeliverSignal(intf, name string, signal *Signal) {
sh.mu.RLock()
defer sh.mu.RUnlock()
if sh.closed {
return
}
for _, scd := range sh.signals {
scd.deliver(signal)
}
}
func (sh *sequentialSignalHandler) Terminate() {
sh.mu.Lock()
defer sh.mu.Unlock()
if sh.closed {
return
}
for _, scd := range sh.signals {
scd.close()
close(scd.ch)
}
sh.closed = true
sh.signals = nil
}
func (sh *sequentialSignalHandler) AddSignal(ch chan<- *Signal) {
sh.mu.Lock()
defer sh.mu.Unlock()
if sh.closed {
return
}
sh.signals = append(sh.signals, newSequentialSignalChannelData(ch))
}
func (sh *sequentialSignalHandler) RemoveSignal(ch chan<- *Signal) {
sh.mu.Lock()
defer sh.mu.Unlock()
if sh.closed {
return
}
for i := len(sh.signals) - 1; i >= 0; i-- {
if ch == sh.signals[i].ch {
sh.signals[i].close()
copy(sh.signals[i:], sh.signals[i+1:])
sh.signals[len(sh.signals)-1] = nil
sh.signals = sh.signals[:len(sh.signals)-1]
}
}
}
type sequentialSignalChannelData struct {
ch chan<- *Signal
in chan *Signal
done chan struct{}
}
func newSequentialSignalChannelData(ch chan<- *Signal) *sequentialSignalChannelData {
scd := &sequentialSignalChannelData{
ch: ch,
in: make(chan *Signal),
done: make(chan struct{}),
}
go scd.bufferSignals()
return scd
}
func (scd *sequentialSignalChannelData) bufferSignals() {
defer close(scd.done)
// Ensure that signals are delivered to scd.ch in the same
// order they are received from scd.in.
var queue []*Signal
for {
if len(queue) == 0 {
signal, ok := <- scd.in
if !ok {
return
}
queue = append(queue, signal)
}
select {
case scd.ch <- queue[0]:
copy(queue, queue[1:])
queue[len(queue)-1] = nil
queue = queue[:len(queue)-1]
case signal, ok := <-scd.in:
if !ok {
return
}
queue = append(queue, signal)
}
}
}
func (scd *sequentialSignalChannelData) deliver(signal *Signal) {
scd.in <- signal
}
func (scd *sequentialSignalChannelData) close() {
close(scd.in)
// Ensure that bufferSignals() has exited and won't attempt
// any future sends on scd.ch
<-scd.done
}
+1 -1
View File
@@ -137,7 +137,7 @@ func ParseSignatureMust(s string) Signature {
return sig return sig
} }
// Empty retruns whether the signature is the empty signature. // Empty returns whether the signature is the empty signature.
func (s Signature) Empty() bool { func (s Signature) Empty() bool {
return s.str == "" return s.str == ""
} }
+1
View File
@@ -10,6 +10,7 @@ package dbus
/* /*
const int sizeofPtr = sizeof(void*); const int sizeofPtr = sizeof(void*);
#define _WANT_UCRED #define _WANT_UCRED
#include <sys/types.h>
#include <sys/ucred.h> #include <sys/ucred.h>
*/ */
import "C" import "C"
+6
View File
@@ -142,3 +142,9 @@ func (v Variant) String() string {
func (v Variant) Value() interface{} { func (v Variant) Value() interface{} {
return v.value return v.value
} }
// Store converts the variant into a native go type using the same
// mechanism as the "Store" function.
func (v Variant) Store(value interface{}) error {
return storeInterfaces(v.value, value)
}
+2 -2
View File
@@ -12,7 +12,7 @@ github.com/cilium/ebpf/internal/unix
# github.com/containerd/console v1.0.1 # github.com/containerd/console v1.0.1
## explicit ## explicit
github.com/containerd/console github.com/containerd/console
# github.com/coreos/go-systemd/v22 v22.1.0 # github.com/coreos/go-systemd/v22 v22.3.1
## explicit ## explicit
github.com/coreos/go-systemd/v22/activation github.com/coreos/go-systemd/v22/activation
github.com/coreos/go-systemd/v22/dbus github.com/coreos/go-systemd/v22/dbus
@@ -24,7 +24,7 @@ github.com/cyphar/filepath-securejoin
# github.com/docker/go-units v0.4.0 # github.com/docker/go-units v0.4.0
## explicit ## explicit
github.com/docker/go-units github.com/docker/go-units
# github.com/godbus/dbus/v5 v5.0.3 # github.com/godbus/dbus/v5 v5.0.4
## explicit ## explicit
github.com/godbus/dbus/v5 github.com/godbus/dbus/v5
# github.com/golang/protobuf v1.4.3 # github.com/golang/protobuf v1.4.3