Does anybody know why dbus exists? I’ve been wracking my brain trying to come up with a usecase for dbus that isn’t already covered by Unix sockets.

You want to remotely control a daemon? Use sockets. You want the daemon to respond to the client? Sockets. Want to exchange information in json? plaintext? binary data? Sockets can do it. Want to restrict access to a socket? Go ahead, change the socket’s permissions. Want to prevent unauthorized programs from pretending to be someone they’re not? Change the permissions of the directory containing the socket. Want network transparency? That’s why we have abstract sockets.

Plenty of well-established software uses sockets. Music player daemon uses sockets. BSPWM uses sockets. Tmux uses sockets. Pipewire uses sockets. Dhcpcd uses sockets. Heck, dbus itself relies on sockets!

For developers, using sockets is easy. I once wrote a program that interfaced with BSPWM, and it was a breeze. Dbus, on the other hand, not so much. I tried writing a Python script that would contact Network Manager and check the WiFi signal strength. Right off the bat I’m using some obscure undocumented package for interfacing with dbus. What is an introspection? What is a proxy object? What is an interface? Why do I need 60 lines of (Python!) code for a seemingly trivial operation?

So why do some developers decide to use dbus when they could just use unix sockets and save a lot of hassle for themselves and others?

  • renzev@lemmy.worldOP
    link
    fedilink
    arrow-up
    8
    ·
    11 months ago

    modular daemons

    A message bus won’t magically remove the need for developers to sit down together and agree on how some API would work. And not having a message bus also doesn’t magically prevent you from allowing for alternative implementations. Pipewire is an alternative implementation of pulseaudio, and neither of those rely on dbus (pulse can optionally use dbus, but not for its core features). When using dbus, developers have to agree on which path the service owns and which methods it exposes. When using unix sockets, they have to agree where the socket lives and what data format it uses. It’s all the same.

    It can even start the receiving daemon if it is not yet running.

    We have a tool for that, it’s called an init system. Init systems offer a large degree of control over daemons (centralized logging? making sure things are started in the correct order? letting the user disable and enable different daemons?). Dbus’ autostart mechanism is a poor substitute. Want to run daemons per-user instead of as root? Many init systems let you do that too (I know systemd and runit do).

    • aport@programming.dev
      link
      fedilink
      arrow-up
      115
      ·
      11 months ago

      “Bro just use sockets lol” completely misses the point. When you decide you want message based IPC, you need to then design and implement:

      • Message formatting
      • Service addressing
      • Data marshalling
      • Subscriptions and publishing
      • Method calling, marshalling of arguments and responses
      • Broadcast and 1:1 messaging

      And before you know it you’ve reimplemented dbus, but your solution is undocumented, full of bugs, has no library, no introspection, no debugging tools, can only be used from one language, and in general is most likely pure and complete garbage.

      • hglman@lemmy.ml
        link
        fedilink
        English
        arrow-up
        8
        ·
        11 months ago

        Well said. There are so many details to making code work that can so often be avoided by using the right tooling. OP said it was harder to get started, which implies they did not handle the details and have code not actually robust to all kinds of edge cases. Maybe they don’t need it but they probably do.

      • AVincentInSpace@pawb.social
        link
        fedilink
        English
        arrow-up
        6
        ·
        edit-2
        11 months ago

        Message formatting

        still have to do that with dbus

        Service addressing

        They’re Unix sockets, dude, they’re file paths in /run

        Data marshalling

        Still have to do that with dbus, also that’s the same thing as message formatting

        Pubsub

        Again, sockets. One application binds and many can connect (how often do you really need more than one application to respond to a method call? That’s a valid reason to use dbus in lieu of sockets, but how often do you need it?)

        Method calling, marshalling of arguments and responses

        They’re called “unix doors”, and that’s the third time you’ve said marshalling. As for that, language agnostic data marshalling is kind of a solved problem. I’m personally a fan of msgpack but JSON works too if you want to maximize compatibility. Or XML if you really want to piss off the people who interact with your API.

        Broadcast and 1:1 messaging

        Sockets and doors can only do 1:1, and that’s true enough, but it occurs to me that 99% of use cases don’t need that and thus don’t need dbus. dbus can still be used for those cases, but less load on dbus daemon = less load on system. Also you said that already with pubsub.

        As for that blob at the bottom, again, who said anything about there not being a language agnostic library? It’d be a lot of work to make one, sure, but that doesn’t mean it’s impossible. Besides, most of the work has been done for you in the form of language agnostic marshalling libraries which as you said are like 50% of the problem. The rest is just syscalls and minor protocol standardization (how to reference FDs passed through the door in the msgpack data etc.)

        And what I’ve just described isn’t a reimplementation of dbus without any of the good parts, it’s a reimplementation of dbus on top of the kernel instead of on top of a daemon that doesn’t need to be there.

    • Ramin Honary@lemmy.ml
      link
      fedilink
      English
      arrow-up
      37
      ·
      edit-2
      11 months ago

      It can even start the receiving daemon if it is not yet running.

      We have a tool for that, it’s called an init system.

      The init system is for trusted system services that can talk directly to hardware. Unless you are working on a single-user system with no security concerns of any kind, you might consider using init to launch persistent user land or GUI processes.

      DBus is for establishing a standard publish/subscribe communication protocol between user applications, and in particular, GUI applications. And because it is standard, app developers using different GUI frameworks (Gtk, Qt, WxWidgets, FLTK, SDL2) can all publish/subscribe to each other using a common protocol.

      It would be certainly be possible to establish a standard place in the /tmp directory and a standard naming scheme for sockets and temporary files so that applications can obtain a view of other running applications and request to receive message from other applications using ordinary filesystem APIs, but DBus does this without needing the /tmp directory. A few simple C APIs replace the need for naming and creating your temporary files and sockets.

      • AVincentInSpace@pawb.social
        link
        fedilink
        English
        arrow-up
        5
        ·
        edit-2
        11 months ago

        …systemd very much does use the init system to launch userland and GUI processes. That’s how GNOME works.

        Dbus is for interprocess communication. The fact that its primary use case is communication between desktop applications is hardly relevant to its design. I don’t see how GUI frameworks are at all relevant, or how it would be possible to create an interprocess communication mechanism that only worked with one GUI framework without some heroic levels of abstraction violation (which I would not put past Qt, but that’s another story).

        I don’t see why having an entire dbus daemon running in the background is better than having a cluttered /tmp or /run directory.

    • cbarrick@lemmy.world
      link
      fedilink
      English
      arrow-up
      11
      ·
      11 months ago

      Let’s say you want to write a GUI for connecting to networks.

      In the backend, you have NetworkManager, systemd-networkd, ConnMann, netctl, dhcpcd, …

      Dbus could be a good way to expose a common API surface for clients.