dbus how to reconnect to a new session bus daemon
Question
As far as I understand it, a dbus user connects to the session bus daemon if the environment defines two variables like:
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-1cAnv4I,guid=3a453c40b5034f
DBUS_SESSION_BUS_PID=102
If the daemon stops and we start a new daemon by dbus-launch, we will get new values for the environment. In this case how the new values can be propagated into a running user process without restart?
Solution 2
The logic to reconnect to a new dbus daemon should involve a few components and events:
A bus-monitor which tells the application whether the bus is still up, or down, or restarted.
- When the bus is restarted, the new bus address will be sent to the application.
The application which responses to the down and restart events:
- If the bus is down or restarted, close everything and go back to the beginning of the bus cycle before the call to
dbus_bus_get()
. - If the bus is down, wait till bus is restarted.
- If the bus is restarted, modify the process environment variable
DBUS_SESSION_BUS_ADDRESS
to the new dbus address, then proceed the new bus cycle by callingdbus_bus_get()
.
- If the bus is down or restarted, close everything and go back to the beginning of the bus cycle before the call to
If you read the code in dbus/dbus_bus.c
and follow the functions dbus_bus_get()
-> internal_bus_get()
-> init_connections_unlocked()
, you may see the above logic is what you can do. Or you may see other approaches of doing the same thing. Please leave a comment if you know other approaches or have other thinking.
Edit: Verified the approach with more details:
- After
dbus_bus_get()
, calldbus_connection_set_exit_on_disconnect(conn,FALSE)
so that the application will keep running after the dbus daemon disconnects. - Add a dumb signal receiver that calls
dbus_connection_read_write(conn,0)
. If the dbus connection is lost it returns aFALSE
. That is used to decide when to close the dbus cycle. Drain the message queue withdbus_connection_pop_message(conn)
despite the connection is closed. - Close dbus cycle by
dbus_connection_unref(conn)
thendbus_shutdown()
. If it is not shutdown the call todbus_bus_get()
will not make use of the new environment variable. - Use
setenv(char * name, char * value)
to set session bus address.
OTHER TIPS
One way to get address after restart is to query corresponding X11 property:
dbus-daemon sets _DBUS_SESSION_BUS_ADDRESS
property of _DBUS_SESSION_BUS_SELECTION_[hostname]_[uuid]
selection owner (uuid is content of /var/lib/dbus/machine-id
). This is the code I use to read the this value: https://github.com/sidorares/node-dbus/blob/master/lib/address-x11.js