g_bus_own_name does not always call name_lost_handler when _REPLACE and _ALLOW_REPLACEMENT are set
When g_bus_own_name is called with G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT and G_BUS_NAME_OWNER_FLAGS_REPLACE flags, i.e. like this:
guint id = g_bus_own_name(G_BUS_TYPE_SESSION,
SERVICE_NAME,
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
G_BUS_NAME_OWNER_FLAGS_REPLACE,
on_bus_acquired,
on_name_acquired,
on_name_lost,
NULL,
NULL);
... there is a race situation that the on_name_lost handler is not always called if the DBus name is immediately lost.
The likely reason for this is that the gio subscribes to NameLost and NameAcquired messages only after the name is acquired. That is, if the name is lost before subscribing to the signal, then the signal is not received. The implementation is here: https://gitlab.gnome.org/GNOME/glib/blob/master/gio/gdbusnameowning.c#L333
See the attachment name_own_race_test.c for a full test application source code to replicate the issue. It requires maybe 30 runs to see the race situation happening.
Example run:
~$ killall a_test_x ; sleep 2 && (./a_test_x & ./a_test_x)
a_test_x: no process found
id: 1
id: 1
Got the bus
Got the bus
Got name name com.example.my_test
Got name name com.example.my_test
(no more gets printed)
Interpretation: The both instances are seeing they got the DBus name. No on_name_lost handler is called.
This is what is visible with dbus-monitor --session:
method call time=1536319764.080277 sender=:1.102 -> destination=org.freedesktop.DBus serial=1 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=Hello
method return time=1536319764.080294 sender=org.freedesktop.DBus -> destination=:1.102 serial=1 reply_serial=1
string ":1.102"
signal time=1536319764.080299 sender=org.freedesktop.DBus -> destination=(null destination) serial=515 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
string ":1.102"
string ""
string ":1.102"
signal time=1536319764.080304 sender=org.freedesktop.DBus -> destination=:1.102 serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired
string ":1.102"
method call time=1536319764.080706 sender=:1.103 -> destination=org.freedesktop.DBus serial=1 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=Hello
method return time=1536319764.080726 sender=org.freedesktop.DBus -> destination=:1.103 serial=1 reply_serial=1
string ":1.103"
signal time=1536319764.080730 sender=org.freedesktop.DBus -> destination=(null destination) serial=516 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
string ":1.103"
string ""
string ":1.103"
signal time=1536319764.080736 sender=org.freedesktop.DBus -> destination=:1.103 serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired
string ":1.103"
method call time=1536319764.081528 sender=:1.102 -> destination=org.freedesktop.DBus serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=RequestName
string "com.example.my_test"
uint32 3
signal time=1536319764.081544 sender=org.freedesktop.DBus -> destination=(null destination) serial=517 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
string "com.example.my_test"
string ""
string ":1.102"
signal time=1536319764.081553 sender=org.freedesktop.DBus -> destination=:1.102 serial=3 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired
string "com.example.my_test"
method return time=1536319764.081557 sender=org.freedesktop.DBus -> destination=:1.102 serial=4 reply_serial=2
uint32 1
method call time=1536319764.081560 sender=:1.103 -> destination=org.freedesktop.DBus serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=RequestName
string "com.example.my_test"
uint32 3
signal time=1536319764.081568 sender=org.freedesktop.DBus -> destination=:1.102 serial=5 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameLost
string "com.example.my_test"
signal time=1536319764.081572 sender=org.freedesktop.DBus -> destination=(null destination) serial=518 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
string "com.example.my_test"
string ":1.102"
string ":1.103"
signal time=1536319764.081581 sender=org.freedesktop.DBus -> destination=:1.103 serial=3 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired
string "com.example.my_test"
method return time=1536319764.081584 sender=org.freedesktop.DBus -> destination=:1.103 serial=4 reply_serial=2
uint32 1
The DBus works correctly, but gio just don't get the NameLost signal.
To fix this, perhaps the gio could subscribe to signals after getting the bus connection and before requesting the name.
This was tested with glib version 2.56.1-2ubuntu1.