Thanks Simon. Thanks for the extensive info; however it needs some hours (if not days :P) to be digested.
On Tue, Dec 25, 2012 at 9:24 PM, Simon McVittie < simon.mcvit...@collabora.co.uk> wrote: > On 24/12/12 08:26, Ajay Garg wrote: > > For a recap of the brief history, I have a parent process, that is > > spawning a child process via "subprocess". > > Currently, the child-process is a GUI process; however, I intend to > > "behave" it as a dbus-service as well. > > In general that is something that can work, but it's necessary to > understand a bit about how main loops work, and how the modules of your > process deal with a main loop. > > Just saying "GUI" is not very informative: there are dozens of GUI > frameworks that you might be using, each with their own requirements and > oddities. If you say Gtk, or Qt, or Tk, or Windows MFC, or whatever > specific GUI framework you're using, then it becomes possible to say > something concrete about your situation. > > Based on later mails in the thread you seem to be using Gtk. > > I should note here that you seem to be using PyGtk (the "traditional" > Gtk 2 Python binding), which is deprecated. The modern version is to use > PyGI, the Python GObject-Introspection binding, and Gtk 3. > > When using PyGI, you have a choice of two D-Bus implementations: either > GDBus (part of gi.repository.GIO), or dbus-python ("import dbus"). I > would recommend GDBus, since dbus-python is constrained by backwards > compatibility with some flawed design decisions. > > However, assuming you're stuck with dbus-python: > > > I then used composition, wherein another class, "RemoteListener" > > deriving from "dbus.service.Object" was made an attribute of the "main" > > class. That worked. > > However, when I do > > > > dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) > > GObject.mainloop.run() > > > > in the "RemoteListener"'s __init__ method, the GUI of the "main" class > > fails to load (apparently, because the "mainloop.run()" causes the > > singular, main-thread to go into busy-wait). > > Almost; it's not a busy-wait. GObject.mainloop.run() is the equivalent > of this pseudocode: > > def run(self): > while not global_default_main_context.someone_has_called_quit: > if global_default_main_context.has_more_events(): > global_default_main_context.process_next_event() > else: > global_default_main_context.wait_for_an_event() > > so it will loop until someone calls GObject.mainloop.quit() or > equivalent, or forever if that never happens - but as long as nothing > "interesting" happens, it will block on a poll() or select() syscall in > what my pseudocode calls wait_for_an_event(), which is the right thing > to do in event-driven programming like GLib/Gtk. > > (If you replace the last line of my pseudocode with "continue", that > would be a busy-wait.) > > > I tried option b), but now instantiating "RemoteListener" in a separate > > thread > > It is unclear whether the dbus-glib main loop glue (as set up by > DBusGMainLoop) is thread-safe or not. The safest assumption is always > "if you don't know whether foo is thread-safe, it probably isn't". In > any case, if it *is* thread-safe, the subset of it that's exposed > through dbus-python isn't enough to use it in multiple threads. > > GDBus, as made available via PyGI (specifically, gi.repository.GIO), is > known to be thread-safe. > > > Is there a way to run GUI and a dbus-service together? > > The general answer: only if either the GUI and the D-Bus code > run in different threads, or if they run in the same thread and can be > made to share a main context. > > The specific answer for Gtk: yes, they can easily share a main context. > > This: > > > dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) > > sets up dbus-python's mainloop integration to integrate with the global > default main-context in GLib (implementation detail: it currently uses > dbus-glib to do that). What that means is that whenever a D-Bus > connection started by dbus-python wants to listen for events on a > socket, or wait for a timeout, it will ask GLib to add those to the > global default main context as event sources. > > This: > > > GObject.mainloop.run() > > iterates GLib's global default main context, analogous to the pseudocode > I mentioned before. Any "interesting" events that happen will cause your > code to be executed. > > A typical GUI application also needs to run the main loop to > wait for events. In PyGtk, you'd typically do that with: > > > Gtk.main() > > Gtk also uses GLib's global default main context, so this is pretty > similar to GObject.mainloop.run() - if you just remove the call to > GObject.mainloop.run() and use Gtk.main() instead, everything should be > fine. > > > As per http://www.pygtk.org/pygtk2reference/class- > > gobjectmainloop.html, it seems that we must be able to add event > > sources to gobject.mainloop > > Yes. For instance, gobject.timeout_add(), gobject.idle_add() and > gobject.io_add_watch() all add event sources to the default main context. > > dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) tells dbus-python > that when it needs to add an event source to "the" main loop, it should > use equivalent C functions in GLib to do so. > > (In principle, DBusGMainLoop ought to take a GObject.MainContext as an > optional argument - but that's never been implemented, and it currently > always uses the default main context, which is the same one Gtk uses, > and which should only be iterated from the main thread.) > > > Once the event sources are added, each instance of gobject.mainloop > > (in its particular thread), will cater to only those sources. > > No, that's not true; gobject.mainloop is a namespace for a set of global > functions, not an object. If you must use multiple threads (not > recommended), please see the GLib C API documentation for details of how > main loops and main contexts relate, then the PyGtk documentation to see > how that translates into Python. > > > How is dbus."mainloop.glib.DBusGMainLoop(set_as_default=True)" > > related to gobject.mainloop? > > It instantiates a new DBusGMainLoop and sets it as dbus-python's global > default main-loop-integration object. (With hindsight, DBusGMainLoop was > a poor choice of name - it should have been DBusGMainIntegration or > something.) The result is that whenever a new dbus.connection.Connection > is instantiated, it will call methods on that DBusGMainLoop to connect > its event sources up to the default GLib main context, which is the same > one used by Gtk. > > dbus.bus.BusConnection, dbus.Bus, dbus.SessionBus etc. are > dbus.connection.Connection subclasses, so anything I say about > dbus.connection.Connection applies equally to them. > > > How is dbus."mainloop.glib.DBusGMainLoop(set_as_default=False)" > > related to gobject.mainloop? > > It instantiates a new DBusGMainLoop and doesn't use it for anything. If > you save the returned DBusGMainLoop in a variable (e.g. > my_dbus_g_main_loop = DBusGMainLoop(...)), then you can pass a keyword > argument mainloop=my_dbus_g_main_loop to a dbus.connection.Connection > constructor, and that dbus.connection.Connection will use that > DBusGMainLoop instead of dbus-python's global default. In practice, only > a very unusual application would need to do that. > > There is currently no point in having more than one DBusGMainLoop; it > would become useful if dbus-glib was thread-safe, and if dbus-python > supported non-default GLib main-contexts. > > > Is it necessary at all to specify > > "mainloop.glib.DBusGMainLoop(set_as_default=True)" or > > "mainloop.glib.DBusGMainLoop(set_as_default=False)" when using > > gobject.mainloop? > > Yes. Otherwise, dbus-python has no way to know that your application is > going to be iterating the GLib main loop, as opposed to Qt or Tk or > Enlightenment or something. > > > currently for the client, I am having the (client) (parent) process > > run the command "dbus-send" via the python-subprocess API. > > Does there exist a python API to do it in a cleaner manner? > > Yes, either dbus-python or GDBus. Each of those can do everything > dbus-send can, and more. > For a start, could you please point me to the paradigm to send a dbus-signal from the client to the server (where the server has the "add_to_signal_receiver" been set up). >From the limited googling that I did, I remember someone saying that for sending a signal, the typical setting-up-of-a-proxy-object is not required; however, I could not hit upon the exact dbus-python mechanism to send a signal :-\ > > S > _______________________________________________ > dbus mailing list > d...@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dbus > -- Regards, Ajay
_______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com