mvidner / ruby-dbus

A Ruby binding for DBus
GNU Lesser General Public License v2.1
170 stars 48 forks source link

Question: can I export multiple services from a single process - dbus restriction? #69

Closed mistergibson closed 1 year ago

mistergibson commented 6 years ago

I'm not sure if I got your question right but I will repurpose this report for my current problem:

A connection can have more than one well-known name (the letter-dotted one), ruby-dbus doesn't support it.

For example on my desktop I have one connection using 3 well-known names:

$ busctl --user | grep Thunar
NAME                          PID PROCESS USER   CONNECTION UNIT            SESSION DESCRIPTION
:1.18                        2448 Thunar  martin :1.18      session-1.scope 1       -
org.freedesktop.FileManager1 2448 Thunar  martin :1.18      session-1.scope 1       -
org.xfce.FileManager         2448 Thunar  martin :1.18      session-1.scope 1       -
org.xfce.Thunar              2448 Thunar  martin :1.18      session-1.scope 1       -
$ busctl --user tree org.xfce.Thunar
└─/org
  ├─/org/freedesktop
  │ └─/org/freedesktop/FileManager1
  └─/org/xfce
    ├─/org/xfce/FileManager
    └─/org/xfce/Thunar

This is persumably to offer a custom Thunar interface as well as a common FileManager interface.

Another use case is to implement multiple loosely related services in the same process to save on memory overhead (like Agama Manager+Users).

Currently ruby-dbus cannot do this, it assumes that your service has exactly one well-known name and you call:

service = bus.request_service("org.example.Widget1")
service.export(Widget.new("/org/example/Widget1"))
some_main_loop.run

Even if you try to trick the library requesting 2 "services" and exporting the objects on the latter one which gets remembered internally:

s1 = bus.request_service("org.example.Widget1")
s2 = bus.request_service("org.example.Gadget1")
s2.export(Widget.new("/org/example/Widget1"))
s2.export(Gadget.new("/org/example/Widget1"))

It will kind of work, eventually producing the object tree what you want, but importantly for autostarted services, the second request_service call will already start processing method calls for the objects that haven't been exported yet. So the first method call will fail.

Original report:

Dear Developer:

Can I export more than one service (assuming differing names of course) from a single process? I noticed that you use class variables instead of instance variables for the interface.

Thanks,

G.

mistergibson commented 6 years ago

Also - how do I 'un-export' a service when I'm done with it (other than exiting the process)?

mvidner commented 6 years ago

Hi!

Regarding exporting multiple services: I think you can achieve this by instantiating multiple Connections, specifically ASystemBuses or ASessionBuses. But I have never tried this so it is possible that something breaks it.

Regarding unexporting a service, it is possible in a crude way by calling ReleaseName, see the file server_spec.rb for an example.

mvidner commented 1 year ago

Fixed in #135, released 0.23.0.beta1