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."

------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
Gambas-user mailing list
Gambas-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/gambas-user

Reply via email to