Giter Club home page Giter Club logo

dbus's Introduction

Build Status

dbus

dbus is a simple library that implements native Go client bindings for the D-Bus message bus system.

Features

  • Complete native implementation of the D-Bus message protocol
  • Go-like API (channels for signals / asynchronous method calls, Goroutine-safe connections)
  • Subpackages that help with the introspection / property interfaces

Installation

This packages requires Go 1.12 or later. It can be installed by running the command below:

go get github.com/godbus/dbus/v5

Usage

The complete package documentation and some simple examples are available at pkg.go.dev. Also, the _examples directory gives a short overview over the basic usage.

Projects using godbus

  • fyne a cross platform GUI in Go inspired by Material Design.
  • fynedesk a full desktop environment for Linux/Unix using Fyne.
  • go-bluetooth provides a bluetooth client over bluez dbus API.
  • iwd go bindings for the internet wireless daemon "iwd".
  • notify provides desktop notifications over dbus into a library.
  • playerbm a bookmark utility for media players.
  • rpic lightweight web app and RESTful API for managing a Raspberry Pi

Please note that the API is considered unstable for now and may change without further notice.

License

go.dbus is available under the Simplified BSD License; see LICENSE for the full text.

Nearly all of the credit for this library goes to github.com/guelfey/go.dbus.

dbus's People

Contributors

alexlarsson avatar amenzhinsky avatar andrew-hoff avatar andydotxyz avatar aperum avatar bcwaldon avatar black-desk avatar electricface avatar golangaccount avatar guelfey avatar jamesd avatar jessevdk avatar jhenstridge avatar jonboulle avatar jsouthworth avatar jubalh avatar kolyshkin avatar marselester avatar mechmind avatar muesli avatar pck avatar philips avatar sarim avatar schachmat avatar tdubrownik avatar tmthrgd avatar varialus avatar vincenospam avatar wdouglass avatar wzshiming avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dbus's Issues

Example for getting a property?

Hi,

I'm trying to fetch a single property on a DBus object and not having any luck. Here's a command-line example of what I'm trying to do:

% gdbus call -y -d org.freedesktop.resolve1 -o /org/freedesktop/resolve1/link/_32 -m org.freedesktop.DBus.Properties.Get org.freedesktop.resolve1.Link DNS
(<[(2, [byte 0x08, 0x08, 0x08, 0x08]), (2, [0x08, 0x08, 0x04, 0x04])]>,)

Here's my non-working code:

	conn, err := dbus.SessionBus()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Failed to connect to session bus:", err)
		os.Exit(1)
	}

	bo := conn.Object("org.freedesktop.resolve1.Manager", "/org/freedesktop/resolve1/link/_32")
	variant, err := bo.GetProperty("DNS")

	if err != nil {
		log.Fatalln("Error getting property:", err)
	}

	log.Println("Variant --->", variant.String)

Could you help me with a simple example for fetching a property from an object? I don't see anything like this in the _examples directory. Thanks.

New tag

Hello, guys, how about v1.0.1? I see that you've fixed vet warnings since last release for example.
Thanks!

Impossible to implement interfaces with lower-case methods

When attempting to implement already-defined dbus interfaces (this, for example), one often runs into lower-case method names. However, if I understand how Export() currently works, that's not possible in this library.

If I'm wrong, can you give me some advice for how to accomplish this?

Object is impossible to mock or fake

Take the following extremely simple chunk of code:

busObject := connection.Object("my.object.name", "/")
var returnValue string
busObject.Call("my.interface.method", 0, "foo").Store(&returnValue)

That chunk is impossible to test without an actual DBus bus. The reason is quite simple: conn.Object() returns a dbus.Object rather than an interface implementing a dbus.Object which can then be implemented by the client for mocking/faking purposes.

Names require service files to call methods

Hello, I am not a dbus expert so forgive me if this is programmer error.

I am following the examples and I want to call a method like could be executed from the command line like so:

dbus-send --print-reply --dest=org.mpris.MediaPlayer2.vlc /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause

which should make my media player play.

Here is a program that I would expect to do this with godbus:

package main

import (
    "github.com/godbus/dbus"
)

func main() {
    conn, err := dbus.SessionBus()
    if err != nil {
        panic(err)
    }
    obj := conn.Object("org.mpris.MediaPlayer2.vlc", "/org/mpris/MediaPlayer2")
    call := obj.Call("org.mpris.MediaPlayer2.Player.PlayPause", 0)
    if call.Err != nil {
        panic(call.Err)
    }
}

But I get this error:

panic: The name org.mpris.MediaPlayer2.vlc was not provided by any .service files

with a stack trace. I believe it is correct that there is not any such service file that provides org.mpris.MediaPlayer2.vlc, but vlc is running, and when I list names with dbus-send, it appears in the returned array. However, when I run the example in the examples folder to list names, it does not appear in the returned array.

Could someone help me out with this?

Thanks.

DBus activation doesn't work for initial method call

DBus activation has the following event flow:

  1. Process A makes a DBus method call with DBus name "com.example.Foo" and method "com.example.Interface.MethodName."
  2. DBus notices that there is no process on the bus with the name "com.example.Foo."
  3. DBus launcher looks through /usr/share/dbus-1/services (for session bus services) for a .service file for a DBus service with the name "com.example.Foo." If it doesn't find one, it returns a "No such service" error and breaks this flow.
  4. If it does find one, it launches the process with the information from the .service file.
  5. It waits until the process has been granted the name "com.example.Foo" (i.e the NameAcquired signal).
  6. It sends the method call to the process.

The problem for godbus is the time between steps 5 and 6. Since the name request (and corresponding NameAcquired signal) are handled asynchronously, and the method call is also handled asynchronously, and the time between steps 5 and 6 is minuscule, it's possible (indeed, it happens every time for me) for the NameAcquired signal to be emitted but not completely handled before the method call comes in as well. This results in the method call being discarded since godbus hasn't saved the fact that the name has been acquired, so godbus thinks the message came in via an eavesdrop with no corresponding channel.

This results in the initial method call (which caused the activation) to receive no reply. Subsequent method calls work fine since the NameAcquired signal has since been handled.

There needs to be some way of synchronously acquiring the name (or at least synchronously handling that signal before handling another message), or godbus simply can't be used for DBus activation.

Semantic tag v5.0.0

Hi guys, can someone add v5.0.0 tag on top of v5.0 to follow semantic versioning, it seems like without this modules-aware go get fails to get the 5th release.

https://golang.org/cmd/go/#hdr-Module_compatibility_and_semantic_versioning

% go get -v github.com/godbus/[email protected]
go get github.com/godbus/[email protected]: no matching versions for query "v5.0"

 % go get -v github.com/godbus/[email protected]
go get github.com/godbus/[email protected]: unknown revision v5.0.0

Wrap platform specific calls

From comments below, building on windows goes to:

C:\ProgramData\go-projects\src\github.com\godbus\dbus>go build
# github.com/godbus/dbus
.\transport_unix.go:23: undefined: syscall.MSG_CTRUNC
.\transport_unix.go:127: undefined: syscall.ParseSocketControlMessage
.\transport_unix.go:134: undefined: syscall.ParseUnixRights
.\transport_unix.go:170: undefined: syscall.UnixRights
.\transport_unixcred.go:12: undefined: syscall.Ucred
.\transport_unixcred.go:13: undefined: syscall.UnixCredentials

This should be wrapped so that windows doesn't get confused... worse (because it already is).

Error emitting signal: dbus: connection closed by user

Hi,

I am trying to wrap a library to expose it over DBus. The library provides functionality to query and set Ikea Trådfri light bulbs, and also provides a channel over which notifications are sent when devices are changed through other means (such as a smartphone app or the remote control) so that any user of the library can update its state accordingly.

In my code, I spawn a goroutine which reads from this channel. For every received message I would then like to emit a notification, with the received message as value. The DBus daemon works in that I can query and set light bulbs through e.g. DFeet, but when I press any button on my remote in order to test the signal delivery I get Error emitting signal: dbus: connection closed by user. The provided channel works appropriately in a command line tool accompanying the library. I've been stuck on this for a while and cannot find a clue as to why this is happening, hence this issue.

The relevant code is as follows:

        ...

	err = d.conn.Export(DBusClient{*d.client}, objectRoot, nameRoot)
	if err != nil {
		return fmt.Errorf("Cannot export Trådfri interface: %s\n", err)
	}

	// Request name after exporting interfaces to ensure that the interfaces aren't called before they
	// are exported.
	reply, err := d.conn.RequestName(nameRoot, dbus.NameFlagDoNotQueue)
	if err != nil {
		return fmt.Errorf("Cannot associate name \"%s\": %s\n", nameRoot, err)
	}
	if reply != dbus.RequestNameReplyPrimaryOwner {
		return fmt.Errorf("Name \"%s\" already taken", nameRoot)
	}

        ...

        go d.handleDeviceUpdates()

Where handleDeviceUpdates is:

func (d *DBusDaemon) handleDeviceUpdates() {
	for msg := range d.client.DeviceEvents() {
		err := d.conn.Emit(objectRoot, nameRoot+".DeviceChanged", msg)
		if err != nil {
			fmt.Printf("Error emitting signal: %s\n", err)
		} else {
			fmt.Printf("Emitted signal %s.%s\n", nameRoot+".DeviceChanged", msg.ID)
		}
        }
}

The full code is here. Any comments or pointers are appreciated!

data race in default_handler.go

func (obj *exportedObj) LookupInterface(name string) (Interface, bool) {
	if name == "" {
		return obj, true
	}
	// TODO: data race
	intf, exists := obj.interfaces[name]
	return intf, exists
}

func (obj *exportedObj) AddInterface(name string, iface *exportedIntf) {
	// TODO: data race
	obj.interfaces[name] = iface
}

log

==================
WARNING: DATA RACE
Read at 0x00c420c0b9e0 by goroutine 411:
  runtime.mapaccess2_faststr()
      /home/tp/applications/go/src/runtime/hashmap_fast.go:261 +0x0
  pkg.deepin.io/lib/dbus1.(*exportedObj).LookupInterface()
      /home/tp/program_lang/go/src/pkg.deepin.io/lib/dbus1/default_handler.go:171 +0xa4
  pkg.deepin.io/lib/dbus1.(*Conn).handleCall()
      /home/tp/program_lang/go/src/pkg.deepin.io/lib/dbus1/export.go:136 +0x36a

Previous write at 0x00c420c0b9e0 by goroutine 13:
  runtime.mapassign_faststr()
      /home/tp/applications/go/src/runtime/hashmap_fast.go:694 +0x0
  pkg.deepin.io/lib/dbus1.(*Conn).export()
      /home/tp/program_lang/go/src/pkg.deepin.io/lib/dbus1/default_handler.go:176 +0x3f1
  pkg.deepin.io/lib/dbus1.(*Conn).ExportWithMap()
      /home/tp/program_lang/go/src/pkg.deepin.io/lib/dbus1/export.go:256 +0xa4
  pkg.deepin.io/lib/dbus1.(*Conn).Export()
      /home/tp/program_lang/go/src/pkg.deepin.io/lib/dbus1/export.go:247 +0x90
  pkg.deepin.io/lib/dbusutil.(*ServerObject).Export()
      /home/tp/program_lang/go/src/pkg.deepin.io/lib/dbusutil/object.go:40 +0x3ae
  pkg.deepin.io/lib/dbusutil.(*Service).Export()
      /home/tp/program_lang/go/src/pkg.deepin.io/lib/dbusutil/service.go:135 +0xcd
  pkg.deepin.io/dde/daemon/audio.(*Audio).updateDefaultSink()
      /home/tp/program_lang/go/src/pkg.deepin.io/dde/daemon/audio/audio_stub.go:203 +0x2b5
  pkg.deepin.io/dde/daemon/audio.(*Audio).handleSinkEvent()
      /home/tp/program_lang/go/src/pkg.deepin.io/dde/daemon/audio/audio_events.go:165 +0x23b
  pkg.deepin.io/dde/daemon/audio.(*Audio).initEventHandlers.func3()
      /home/tp/program_lang/go/src/pkg.deepin.io/dde/daemon/audio/audio_events.go:40 +0x58

Client Wrappers?

I made a small client wrapper for org.freedesktop.Notifications interface:
https://github.com/esiqveland/notify

I made it a new project instead of a PR to godbus because I didn't see any other clients like this here.

Is this something you'd be interested to add in here instead?

Error: dbus: wire format error: unexpected EOF

Hello

Getting a property with signature (sa(iiay)ss) produces:

Error: dbus: wire format error: unexpected EOF

I've attached a small client and server to reproduce.
I'm pretty sure the problem is on the client side. I've also attached a small script that uses dbus-send to retrieve the property from the server, which works fine.
I came across the problem trying (from go) to retrieve properties from a StatusNotifierItem service written in C++/Qt

br. Chr.

clientserver.zip

Impossible to export to subtree

Currently in godbus, it's possible to register an object at a given object path, i.e. Export(MyStruct{}, "/foo", "my.interface"), and method calls coming in on that object path are dispatched to that struct.

However, although the dbus spec allows it, it's not possible to register an endpoint for an entire subtree of object paths. In the example above, method calls coming in on the object path /foo/bar will result in a "no such method" error.

There are a number of use-cases for this. In our case, we need to register for an entire subtree in order to take advantage of AppArmor's DBus integration, which means we'd like to see this feature in godbus.

I'm happy to write this feature, but I want to get the OK before beginning.

Keeping in mind the following goals:

  1. Need to be able to register for an entire subtree of object paths
  2. Need to know which object path was used for the method call
  3. Need to know the sender of the message

I propose one of the following ideas:

Method 1

Modify Export functions to support a wildcard in the object path, e.g. Export(MyStruct{}, "/foo/*", "my.interface"). The presence of the wildcard indicates a desire to be called for the entire /foo/ subtree (e.g. /foo/bar, /foo/baz, etc.), and the method dispatching can do method lookups accordingly. This will satisfy (1) above.

(2) and (3) can be satisfied by changing the API of exported methods in MyStruct{} to require that the first parameter accepts a dbus.Message, which allows for access to the lower-level detailed required, e.g.:

type MyStruct struct{}

func (m MyStruct) foo(message dbus.Message, param1, param2 string) (string, *dbus.Error) {
        return "hello world"
}

Using some reflection tricks it may be possible to make that first parameter optional thus not breaking API, but that might make things less obvious.

Summary

Advantages:

  • Easier to write
  • Easier to maintain
  • Intuitive to use

Disadvantages:

  • Probably breaks API
  • Potentially dilutes the clarity of Export usage since it can be used multiple ways

Method 2

Add new ExportSubtree functions that work the same way as the current Export functions, but registers the struct for the entire subtree instead of just that specific object path. For example, ExportSubtree(MyStruct{}, "/foo", "my.interface") would indicate a desire to be called for the entire /foo subtree (e.g. /foo/bar, /foo/baz, etc.), and the method dispatching can do method lookups accordingly. This will satisfy (1) above.

(2) and (3) can be satisfied by requiring that functions on structs exported via ExportSubtree accept a dbus.Message as their first parameter, which allows for access to the lower-level detailed required (same example as the one given in Method 1).

Summary

Advantages:

  • Doesn't break API
  • Obviously works differently from the regular Export functions, so it's user-friendly and clear

Disadvantages:

  • More work to write
  • More work to maintain since two export code paths must be supported

I'm looking to start a discussion here and settle on a solution which I'm then happy to contribute. Thanks for your thoughts!

Proposal: new release v4.0.1 (to include fixes for some issues)

Hi there,
I'm using godbus/dbus quite successfully in a few projects. I had some issues with panics (send on closed channel) sometimes (quite rare).

So I did some research and found this issue: #45 which seems to be exactly the problem I got. The issue was fixed quite a long time ago and I was wondering why it still hit me.
I'am using "glide" or "dep" to vendor all my projects and found out that I'm using the latest release (which currently is v4.0.0, released 19 Apr 2016). Unfortunately this release does not include the fix for issue #45.

To beware future users of godbus/dbus (using vendoring tools and using releases, which I think is the wiedly used standard) making the same mistake like me I'd like to propose publishing a new minor release v4.0.1.

Thank you for your work and regards,
Thomas

Possible deadlock (race) when receiving signals during close

AIUI there's a possible deadlock race when receiving signals during close. I didn't trigger this yet, it is from reading code only. I might be completely misunderstanding everything. Here's the logic:

The signals from conn.Signal(someChan) are sent to that user provided channel here:

ch <- signal

If we use an unbuffered channel, or a channel who has a full buffer, we might block on that line, and if we simultaneously try to run RemoveSignal or conn.Close() then we've deadlocked.

I think the solution is to change that send into a:

select {
	case ch <- signal:
		// send
	case sh.closeChan:
		return
}

And to implement a closeChan struct{} that gets a close() called on it whenever we need to unblock and shutdown. It might also be important to consider doing something similar for the RemoveSignal function, but I haven't looked into that code path as much.

This is related to #8 and possibly also: #1

If you'd like to work on this issue and would like mentorship, please ping @purpleidea here or in #mgmtconfig on Freenode IRC.

Note: this issue came up here: https://github.com/purpleidea/mgmt/blob/677cdea99de89572c4527406204a0a0169560bf5/resources/nspawn.go#L179

Thanks!
// cc @jonathangold

Unknown object when calling method of an sd-bus program

Hi, I wrote a Go program using this library and I want to call other C++ program's method via D-Bus. But for some reason, the Go program says 'Unknown object /foo/bar/Baz'. I used D-Feet and busctl and there seems to be no problem there. Does anyone have an idea what's going on? I used sd-bus for the C++ program.

Messages can be lost due to asynchronous send

Since we have an outWorker that runs asynchronously to send messages on the bus, if an signal is sent and the program exits it may not be relayed on the bus. This makes writing a oneshot utility to signal on the bus difficult. This asynchronous outWorker seems unnecessary. I propose refactoring the library to eliminate this difficulty.

kdbus

So kdbus looks like it will be added for linux 4.1-rc1, would you be open to having that implementation added here as well in like a nice interface, I would be open to helping :)

Allow creating connections from *net.UnixConn

It may be that the connection was opened outside of libdbus (for example when inheriting from fork of an already opened file descriptor). The dbus library should allow to create a connection (with ability to pass fd) from an existing *net.UnixConn

This could be used to communicate using dbus between different processes that don't want to expose their communication to a system or user/session bus.

goroutine leak

Hi,
We are seeing goroutines leaked when using StartTransientUnit. Here is the backtrace of the leaking goroutines:

goroutine 8 [IO wait]:
net.runtime_pollWait(0x7f80b98cfe40, 0x72, 0xc4200c1778)
	/usr/lib/golang/src/runtime/netpoll.go:164 +0x5b
net.(*pollDesc).wait(0xc42005f878, 0x72, 0x1000, 0x0)
	/usr/lib/golang/src/net/fd_poll_runtime.go:75 +0x3a
net.(*pollDesc).waitRead(0xc42005f878, 0xc4202447f0, 0x10)
	/usr/lib/golang/src/net/fd_poll_runtime.go:80 +0x36
net.(*netFD).readMsg(0xc42005f810, 0xc4202447f0, 0x10, 0x10, 0xc42014f320, 0x1000, 0x1000, 0xffffffffffffffff, 0x0, 0x0, ...)
	/usr/lib/golang/src/net/fd_unix.go:304 +0x21c
net.(*UnixConn).readMsg(0xc42000e0b0, 0xc4202447f0, 0x10, 0x10, 0xc42014f320, 0x1000, 0x1000, 0xc4202445fc, 0xc4200c9620, 0xc4202445c3, ...)
	/usr/lib/golang/src/net/unixsock_posix.go:115 +0x93
net.(*UnixConn).ReadMsgUnix(0xc42000e0b0, 0xc4202447f0, 0x10, 0x10, 0xc42014f320, 0x1000, 0x1000, 0xfc14b357c4, 0x7f80b9911db8, 0x7f, ...)
	/usr/lib/golang/src/net/unixsock.go:131 +0xac
github.com/opencontainers/runc/vendor/github.com/godbus/dbus.(*oobReader).Read(0xc42014f300, 0xc4202447f0, 0x10, 0x10, 0x1020, 0xc42014f300, 0x0)
	/root/gosrc/src/github.com/opencontainers/runc/vendor/github.com/godbus/dbus/transport_unix.go:21 +0x91
io.ReadAtLeast(0xfc15522c80, 0xc42014f300, 0xc4202447f0, 0x10, 0x10, 0x10, 0xfc152cac60, 0xfc15260b01, 0xc42014f300)
	/usr/lib/golang/src/io/io.go:307 +0xab
io.ReadFull(0xfc15522c80, 0xc42014f300, 0xc4202447f0, 0x10, 0x10, 0x28, 0x0, 0x0)
	/usr/lib/golang/src/io/io.go:325 +0x5a
github.com/opencontainers/runc/vendor/github.com/godbus/dbus.(*unixTransport).ReadMessage(0xc4201ae010, 0xc4201a49f0, 0xc4200c1e00, 0xc42005f8a8)
	/root/gosrc/src/github.com/opencontainers/runc/vendor/github.com/godbus/dbus/transport_unix.go:85 +0x13a
github.com/opencontainers/runc/vendor/github.com/godbus/dbus.(*Conn).inWorker(0xc420097680)
	/root/gosrc/src/github.com/opencontainers/runc/vendor/github.com/godbus/dbus/conn.go:248 +0x4d
created by github.com/opencontainers/runc/vendor/github.com/godbus/dbus.(*Conn).Auth
	/root/gosrc/src/github.com/opencontainers/runc/vendor/github.com/godbus/dbus/auth.go:118 +0x74b

goroutine 11 [chan receive, 7 minutes]:
github.com/opencontainers/runc/vendor/github.com/godbus/dbus.(*Conn).outWorker(0xc4201c6000)
	/root/gosrc/src/github.com/opencontainers/runc/vendor/github.com/godbus/dbus/conn.go:385 +0x5c
created by github.com/opencontainers/runc/vendor/github.com/godbus/dbus.(*Conn).Auth
	/root/gosrc/src/github.com/opencontainers/runc/vendor/github.com/godbus/dbus/auth.go:119 +0x770

Godbus is blocking when we spam request ?

Hi,

Using godbus to communicate between my process (now reduced to a simple loop) and an other process (coded in Python and working, it uses pycurl to download content from the internet) I've found a problem when i use it intensely. After few minutes, the program blocks and seems to stay in an infinite loop. The same program done in Python works perfectly so I know the problem is not in the other process.

After few investigations, I've found that the problem is in godbus, specially in a worker.

Have you any idea about how to solve this problem?

Bytestrings (ay)

Hi,

I'm the creator of pydbus, DBus bindings for Python. I've stumbled upon the case of bytestrings - ay - which are commonly used to send non-Unicode data over DBus.

Because of the GDBus's API, apps commonly require these strings to be '\0'-terminated. And that's completely unintuitive for high-level languages, and something that requires the user to read API docs.

I'm thinking about solving the problem automatically, and I see two solutions:

  1. Auto-append and auto-strip the last character of bytestrings;
  2. Decree (how?) that GDBus API is wrong, and strings sent over the wire should not be \0-terminated.

Whatever we choose, the solution should be agreed upon by authors of bindings for all languages. That's why I'm here.

Do you have any experience with "ay"-encoded bytestrings?

Relevant discussion: LEW21/pydbus#27

SystemBusPrivate doesn't return a working conn.

to get a working conn need to invoke:

    conn, err := dbus.SystemBusPrivate()
    if err != nil {
        return err
    }
    if err = conn.Auth(nil); err != nil {
        conn.Close()
        return err
    }
    if err = conn.Hello(); err != nil {
        conn.Close()
        return  err
    }

SystemBusPrivate() hangs

SystemBus() works find. Change SystemBus() -> SystemBusPrivate() and the connection blocks. Test case:
Shouldn't SystemBusPrivate() work? Do I have a false assumption about SystemBusPrivate()?

package main
import (
        "fmt"
        "github.com/godbus/dbus"
)

func main() {
// Works
        conn, err := dbus.SystemBus()
// Hanges if swapped for SystemBus()
        //conn, err := dbus.SystemBusPrivate()
        defer conn.Close()
        if err != nil {
                fmt.Println(err)
        }
        call := conn.Object(`org.freedesktop.systemd1`, `/org/freedesktop/systemd1`).Call(`org.freedesktop.DBus.Properties.GetAll`, 0, ``)
        fmt.Println(`After call`)
        if call.Err != nil {
                return
        }
        fmt.Println(`result`, call)
}

New version tag

Can you create new version tag, pls? Seems like major tag of go-systemd using features from master.
Thanks!

Add Unexport

Maybe I'm totally missing something, but I don't see a way to 'unexport' an object

Differentiate this fork from its parent

I've written a pkg to interact with upstart using this. My initial search led me to the guelfey/dbus pkg using which I implemented my pkg. I'm considering moving to using this one (it seems more actively maintained?) but I'm not sure what the plans are for this repo (eventually contribute back to the parent repo?).

I assume other developers might follow this path as well (because google prefers to display the parent repo over this one). There is nothing in the README that differentiates this fork from its parent, especially in terms of planned work/roadmap or even why the fork was created and is maintained separately.

equivarent to python's Interface?

I'm porting below's python script into godbus.

bus = dbus.SessionBus ()
from os.path import expanduser
player = bus.get_object ("org.mpris.MediaPlayer2.rhythmbox", "/org/mpris/MediaPlayer2")
iface = dbus.Interface (player, "org.freedesktop.DBus.Properties")

track = iface.Get("org.mpris.MediaPlayer2.Player","Metadata").get(dbus.String(u'xesam:artist'))[0] + " - " + iface.Get("org.mpris.MediaPlayer2.Player","Metadata").get(dbus.String(u'xesam:title'))

what is equivarent to python's Interface ?

panic during close

Hello,

One of my coworkers using this package to interface with systemd hit a panic recently. The reproduction is hard to provide as you need our insane unit test rig, however the panic is straight forward.

panic: send on closed channel

goroutine 39 [running]:
github.com/godbus/dbus.(*Conn).inWorker(0xc820082ea0)
    /home/jesse/go/src/github.com/godbus/dbus/conn.go:327 +0x1048
created by github.com/godbus/dbus.(*Conn).Auth
    /home/jesse/go/src/github.com/godbus/dbus/auth.go:118 +0xf43

goroutine 1 [runnable]:
syscall.Syscall(0x3, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0)
    /usr/lib/go/src/syscall/asm_linux_amd64.s:18 +0x5
syscall.Close(0x8, 0x0, 0x0)
    /usr/lib/go/src/syscall/zsyscall_linux_amd64.go:296 +0x4a
syscall.forkExec(0x2352860, 0xd, 0xc820430fc0, 0x3, 0x3, 0xc8203cc998, 0x4a4, 0x0, 0x0)
    /usr/lib/go/src/syscall/exec_unix.go:201 +0x540
syscall.StartProcess(0x2352860, 0xd, 0xc820430fc0, 0x3, 0x3, 0xc8203cc998, 0x2, 0x4, 0x0, 0x0)
    /usr/lib/go/src/syscall/exec_unix.go:240 +0x6b
os.startProcess(0x2352860, 0xd, 0xc820430fc0, 0x3, 0x3, 0xc8203ccbd0, 0xc82012c3c0, 0x0, 0x0)
    /usr/lib/go/src/os/exec_posix.go:45 +0x33c
os.StartProcess(0x2352860, 0xd, 0xc820430fc0, 0x3, 0x3, 0xc8203ccbd0, 0x0, 0x0, 0x0)
    /usr/lib/go/src/os/doc.go:24 +0x69
os/exec.(*Cmd).Start(0xc82012c280, 0x0, 0x0)
    /usr/lib/go/src/os/exec/exec.go:328 +0x767
os/exec.(*Cmd).Run(0xc82012c280, 0x0, 0x0)
    /usr/lib/go/src/os/exec/exec.go:255 +0x2d
os/exec.(*Cmd).CombinedOutput(0xc82012c280, 0x0, 0x0, 0x0, 0x0, 0x0)
    /usr/lib/go/src/os/exec/exec.go:424 +0x310
github.com/juju/juju/service/upstart.IsRunning(0xc8202d65b0, 0x0, 0x0)
    /home/jesse/go/src/github.com/juju/juju/service/upstart/upstart.go:46 +0xc3
github.com/juju/juju/service.discoverLocalInitSystem(0x0, 0x0, 0x0, 0x0)
    /home/jesse/go/src/github.com/juju/juju/service/discovery.go:103 +0x121
github.com/juju/juju/service.discoverInitSystem(0x0, 0x0, 0x0, 0x0)
    /home/jesse/go/src/github.com/juju/juju/service/discovery.go:36 +0x43
github.com/juju/juju/service.DiscoverService(0xc820241600, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
    /home/jesse/go/src/github.com/juju/juju/service/discovery.go:23 +0x4b
github.com/juju/juju/mongo.glob.func2(0xc820241600, 0x13, 0x0, 0x0, 0x0, 0x0)
    /home/jesse/go/src/github.com/juju/juju/mongo/service.go:67 +0x89
github.com/juju/juju/mongo.RemoveService(0xc820433420, 0xb, 0x0, 0x0)
    /home/jesse/go/src/github.com/juju/juju/mongo/service.go:84 +0x73
github.com/juju/juju/provider/local.glob.func5(0xc820433420, 0xb, 0x0, 0x0)
    /home/jesse/go/src/github.com/juju/juju/provider/local/environ.go:586 +0x37
github.com/juju/juju/provider/local.(*localEnviron).Destroy(0xc8204c2840, 0x0, 0x0)
    /home/jesse/go/src/github.com/juju/juju/provider/local/environ.go:550 +0x122e
github.com/juju/juju/environs.Destroy(0x7fbb65d0e840, 0xc8204c2840, 0x7fbb644d08f8, 0xc820432740, 0x0, 0x0)
    /home/jesse/go/src/github.com/juju/juju/environs/open.go:296 +0x70
github.com/juju/juju/cmd/juju/commands.(*destroyEnvironmentCommand).Run(0xc8203d5f40, 0xc82027d450, 0x0, 0x0)
    /home/jesse/go/src/github.com/juju/juju/cmd/juju/commands/destroyenvironment.go:109 +0x2dd
github.com/juju/juju/cmd/envcmd.(*environCommandWrapper).Run(0xc8203dd6e0, 0xc82027d450, 0x0, 0x0)
    <autogenerated>:62 +0x65
github.com/juju/juju/cmd/envcmd.(*baseCommandWrapper).Run(0xc8203e2000, 0xc82027d450, 0x0, 0x0)
    /home/jesse/go/src/github.com/juju/juju/cmd/envcmd/base.go:109 +0x9c
github.com/juju/cmd.(*SuperCommand).Run(0xc8201d3600, 0xc82027d450, 0x0, 0x0)
    /home/jesse/go/src/github.com/juju/cmd/supercommand.go:442 +0x697
github.com/juju/cmd.Main(0x7fbb644cb6a8, 0xc8201d3600, 0xc82027d450, 0xc82000a100, 0x4, 0x4, 0x1)
    /home/jesse/go/src/github.com/juju/cmd/cmd.go:279 +0x2fc
github.com/juju/juju/cmd/juju/commands.Main(0xc82000a0f0, 0x5, 0x5)
    /home/jesse/go/src/github.com/juju/juju/cmd/juju/commands/main.go:72 +0x4fa
main.main()
    /home/jesse/go/src/github.com/juju/juju/cmd/juju/main.go:15 +0x3b

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
    /usr/lib/go/src/runtime/asm_amd64.s:1696 +0x1

goroutine 5 [syscall]:
os/signal.loop()
    /usr/lib/go/src/os/signal/signal_unix.go:22 +0x18
created by os/signal.init.1
    /usr/lib/go/src/os/signal/signal_unix.go:28 +0x37
ERROR exit status 2

This occured because his code had called conn.Close while there were Signal messages still being delivered to the inWorker goroutine. Close should wait until inWorker has exited before closing the signal channels.

Export should allow the export of methods that do not end in dbus.Error

One may wish to be able to export objects from packages that do not import the 'dbus' library, and whose methods do not use the dbus.Error return type. When exporting these functions, a wrapper can be generated that will return dbus.Error for them for D-Bus specific failures, and will encapsulate the existing 'error' return if it exists and is the last return from a method. If an 'error' is not returned then the wrapper should only encapsulate D-Bus specific failures.

There is some risk in doing this as it would be a subtle API change that could cause unintended methods to be exported if one is using dbus.Error as a flag that this method should be exported on D-Bus. My suggestion would be to have an 'ExportAll' variant for exporting all methods from an object that are exported to packages.

If no one has any objections I will get this implemented.

d-feet errors out with an Exception

com.github.guelfey.Demo : g-io-error-quark: GDBus.Error:org.freedesktop.DBus.Error.NoSuchObject: No such object (36)

When running server.go

Thanks for your work!

Regression due to fix for #53

@izissise reports:
This change breaks stuff, I call a method with the out signature a{oa{sa{sv}}} with
var res map[dbus.ObjectPath]map[string]map[string]dbus.Variant
It worked yesterday and doesn't today with a type mismatch in dbus.go:99

go.mod doesn't follow requirements

Currently, the go.mod of godbus looks like this:

module github.com/godbus/dbus

and we have a tag called v5.0. This doesn't work for Go modules. Every version must include a major, a minor and a patch number (e.g., v5.0.0):

Modules must be semantically versioned in the form v(major).(minor).(patch), such as v0.1.0, v1.2.3, or v3.0.1. The leading v is required.
-- https://github.com/golang/go/wiki/Modules#modules

Furthermore, modules that are v2 or higher should have a branch for the major version and must include /vX in their module path:

Update the go.mod file to include a /v3 at the end of the module path in the module directive (e.g., module github.com/my/module/v3). Update import statements within the module to also use /v3 (e.g., import "github.com/my/module/v3/foo"). Tag the release with v3.0.0.
-- https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher

Otherwise it's impossible to correctly import godbus as a module.

Introspection doesn't work for paths below the one passed to conn.Export

See the terminal session below for ca.desrt.dconf service using GLib's GDBus:

[krnowak@localhost _examples]$ dbus-send --dest='ca.desrt.dconf' --type=method_call \
--print-reply / org.freedesktop.DBus.Introspectable.Introspect
method return sender=:1.74 -> dest=:1.141 reply_serial=2
   string "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
                      "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<!-- GDBus 2.42.1 -->
<node>
  <node name="ca"/>
</node>
"
[krnowak@localhost _examples]$ dbus-send --dest='ca.desrt.dconf' --type=method_call \
--print-reply /ca org.freedesktop.DBus.Introspectable.Introspect
method return sender=:1.74 -> dest=:1.142 reply_serial=2
   string "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
                      "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<!-- GDBus 2.42.1 -->
<node>
  <node name="desrt"/>
</node>
"
[krnowak@localhost _examples]$ dbus-send --dest='ca.desrt.dconf' --type=method_call \
--print-reply /ca/desrt org.freedesktop.DBus.Introspectable.Introspect
method return sender=:1.74 -> dest=:1.143 reply_serial=2
   string "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
                      "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<!-- GDBus 2.42.1 -->
<node>
  <node name="dconf"/>
</node>
"
[krnowak@localhost _examples]$ dbus-send --dest='ca.desrt.dconf' --type=method_call \
--print-reply /ca/desrt/dconf org.freedesktop.DBus.Introspectable.Introspect
method return sender=:1.74 -> dest=:1.147 reply_serial=2
   string "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
                      "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<!-- GDBus 2.42.1 -->
<node>
  <interface name="org.freedesktop.DBus.Properties">
    <method name="Get">
      <arg type="s" name="interface_name" direction="in"/>
      <arg type="s" name="property_name" direction="in"/>
      <arg type="v" name="value" direction="out"/>
    </method>
    ...
    <signal name="PropertiesChanged">
      <arg type="s" name="interface_name"/>
      <arg type="a{sv}" name="changed_properties"/>
      <arg type="as" name="invalidated_properties"/>
    </signal>
  </interface>
  <interface name="org.freedesktop.DBus.Introspectable">
    ...
  </interface>
  ...
  <node name="shm"/>
  <node name="Writer"/>
  <node name="keyfile"/>
</node>
"

In short - calling Introspect on / (root) returns information that this node has one child node - ca. Then doing the same for /ca yields in child node desrt. For /ca/desrt -> dconf. And finally for /ca/desrt/dconf we are getting a bunch of interfaces. And more child nodes to introspect.

Now, terminal session for server example:

[krnowak@localhost _examples]$ dbus-send --dest='com.github.guelfey.Demo' \
--type=method_call --print-reply / org.freedesktop.DBus.Introspectable.Introspect
Error org.freedesktop.DBus.Error.NoSuchObject: No such object
[krnowak@localhost _examples]$ dbus-send --dest='com.github.guelfey.Demo' \
--type=method_call --print-reply /com org.freedesktop.DBus.Introspectable.Introspect
Error org.freedesktop.DBus.Error.NoSuchObject: No such object
[krnowak@localhost _examples]$ dbus-send --dest='com.github.guelfey.Demo' \
--type=method_call --print-reply /com/github org.freedesktop.DBus.Introspectable.Introspect
Error org.freedesktop.DBus.Error.NoSuchObject: No such object
[krnowak@localhost _examples]$ dbus-send --dest='com.github.guelfey.Demo' \
--type=method_call --print-reply /com/github/guelfey \
org.freedesktop.DBus.Introspectable.Introspect
Error org.freedesktop.DBus.Error.NoSuchObject: No such object
[krnowak@localhost _examples]$ dbus-send --dest='com.github.guelfey.Demo' \
--type=method_call --print-reply /com/github/guelfey/Demo \
org.freedesktop.DBus.Introspectable.Introspect 
method return sender=:1.96 -> dest=:1.152 reply_serial=2
   string "
<node>
    <interface name="com.github.guelfey.Demo">
        <method name="Foo">
            <arg direction="out" type="s"/>
        </method>
    </interface>
    <interface name="org.freedesktop.DBus.Introspectable">
        <method name="Introspect">
            <arg name="out" direction="out" type="s"/>
        </method>
    </interface>
</node> "

That means that services written with go-dbus are not introspectable by d-feet for example.

memory leak for serialUsed

In createCall() object.go
msg.serial = o.conn.getSerial()
o.conn.calls.track(msg.serial, call)

Freeing of serial number and call needs to be performed when the msg type is TypeMethodCall (ie: similar to TypeMethodReply)

Contention between Signal and MethodReply Messages

The inWorker event loop [0] handles both Signal and MethodReply Messages. When handling a Signal, an attempt is made to send an object over a user-provided channel. Obviously if this channel is not ready to receive, the inWorker loop will be blocked from processing any more messages. This causes major problems when Methods are called by the user in response to receipt of a Signal object.

This has been addressed in go-systemd by using two independent dbus.Conn objects (and therefore independent inWorker event loops) [1].

[0]

dbus/conn.go

Line 239 in 8d5cd58

func (conn *Conn) inWorker() {

[1] coreos/go-systemd#64

Callbacks

Is there anyway to get callbacks from notifications?

dbus.Store: type mismatch

I have a struct with an element of the following type (Boolean):

type Boolean bool

func (bit Boolean) UnmarshalJSON(data []byte) error {
    asString := string(data)
    if asString == "1" || asString == "true" || asString == "True" {
        bit = true
    } else if asString == "0" || asString == "false" || asString == "False" || asString == "null" {
        bit = false
    } else {
        fmt.Printf("%+v %+v\n", data, string(data))
        return errors.New(fmt.Sprintf("Boolean unmarshal error: invalid input %s", asString))
    }
    return nil
}

When trying to Store() a struct with "Boolean" field type in it, I get:

dbus.Store: type mismatch

I can't figure out how to get around that.

Support for timeout by passing a context?

Is there any work being done to set timeouts on requests sent to dbus?

If I were to raise a PR to implement this using Go's context library, would that be acceptable? The idea is to mitigate against bugs in dbus (example).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.