[Gambas-user] 'Single instance' app cannot reuse DBus.Name
T Lee Davidson
t.lee.davidson at ...626...
Sat Feb 20 13:32:29 CET 2016
A single instance application is one in which only one instance is allowed to be running at the same time. Checking for an
existing instance is quite regularly done simply with some sort of lock file or socket. If a lock is found, then just quit the
app. But suppose you want to pass the current command line arguments along to the existing instance.
DBus is handy for that. We can check to see if our DBus.Name, "org.gambas.[Application.Name]" by default, is already registered
on the bus and behave accordingly. The pseudo-logic is:
If DBusName.IsRegistered.With.DbusSessionDaemon ' There is already an instance running
Send the command line args, via message, to the existing (primary) instance and quit out of the transient instance
Else
Go ahead and start a 'primary' instance and register our DBus.Name on the bus
End
In Gambas, we would send the message to the existing instance using the general format
"DBus[DBus.Name][/Path/To/MyDBusObject].inMethod()". But, apparently, this particular format invisibly tries to register a
connection on the bus using DBus.Name. This causes a problem, because you cannot register the same name on the bus more than once.
In other words, even if you don't explicitly connect and register a name on the bus, simply trying to send a message on the bus
causes an intrinsic registration; and, an exception. And you cannot use a random, guaranteed-unique name for DBus.Name or else
you wouldn't know what it is and would have no way of knowing 'who' to send the message to.
The solution is to change Dbus.Name in the transient instance just prior to passing along the command line data. Here is my
original, error-producing code:
------
' DBusInterface class file
Inherits DBusObject
Create Static
Public Sub Receiver(myString As String)
Print "Received: " & myString
End
---
' Gambas module file
Public Sub Main()
If DBus["org.freedesktop.DBus"]["/"].NameHasOwner(DBus.Name)
Print DBus.Name & " already has an owner." ' Only one instance allowed
' ' Send command line args to existing instance
DBus[DBus.Name]["/DBusInterface"].Receiver("command line arguments") ' *[1] *[2]
Quit
Else
DBus.Session.Register(DBusInterface, "/DBusInterface")
Print "Press Ctrl+C to quit."
While True
Wait 0.1
Wend
DBus.Session.Unregister(DBusInterface)
Endif
End
------
*[1]: That line caused "org.freedesktop.DBus.Error.Failed: No return value",
and a Segmentation Fault; even though no return value should have been expected.
The fix was to do some name swapping:
' ' Send command line args to existing instance
ReceiverDbusName = DBus.Name 'Preserve receiver name
DBus.Name = "org.gambas.Transient" & Application.Name ' Set different name for transient relay of args.
DBus[ReceiverDbusName]["/DBusInterface"].Receiver("command line arguments")
Problem solved! :-)
--
Lee
__________
"Artificial Intelligence is no match for natural stupidity."
More information about the User
mailing list