0

I am trying to write a Hexchat plugin in Python, which would start a server and then communicate with it using DBus and python-dbus library. Everything works fine, until I try to unload the plugin or close Hexchat (which unloads all plugins). The application freezes. It does not happen if I do not call any method using the DBus.

I tried to pinpoint the problem, so I have created a minimal example:

server.py

import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib


class EchoService(dbus.service.Object):
    def __init__(self):
        DBusGMainLoop(set_as_default=True)
        self.loop = GLib.MainLoop()

        bus_name = dbus.service.BusName(name='com.skontar.Echo', bus=dbus.SessionBus())
        super().__init__(conn=None, object_path='/com/skontar/Echo', bus_name=bus_name)

    def run(self):
        self.loop.run()

    @dbus.service.method(dbus_interface='com.skontar.Echo', in_signature='', out_signature='')
    def quit(self):
        self.loop.quit()

    @dbus.service.method(dbus_interface='com.skontar.Echo', in_signature='s', out_signature='s')
    def echo(self, text):
        print(text)
        return 'ACK'


EchoService().run()

dbus_plugin_unload_test.py

import subprocess
import time

import dbus
import hexchat

__module_name__ = 'dbus_plugin_unload_test'
__module_description__ = 'TBD'
__module_version__ = '1.0'


def get_dbus_interface():
    session_bus = dbus.SessionBus()
    dbus_object = session_bus.get_object(bus_name='com.skontar.Echo',
                                         object_path='/com/skontar/Echo')
    interface = dbus.Interface(object=dbus_object, dbus_interface='com.skontar.Echo')
    return interface


def unload(userdata):
    hexchat.prnt('Unloading {}, version {}'.format(__module_name__, __module_version__))
    global interface
    interface.quit()
    time.sleep(1)
    # raise Exception


hexchat.prnt('Loading {}, version {}'.format(__module_name__, __module_version__))
subprocess.Popen('python3 /home/skontar/Python/Examples/DBus/server.py', shell=True)
time.sleep(1)
interface = get_dbus_interface()
time.sleep(1)
interface.echo('TEST')
hexchat.hook_unload(unload)

In this example, everything works. When I try to unload the plugin or close Hexchat, server exits (so the .quit call works), but Hexchat hangs.

If I comment out both interface.echo('TEST') and interface.quit() it unloads fine, but also the plugin does not do anything useful. I have also found that if I raise Exception at the end of unload callback, everything closes "correctly", nothing hangs.

I am thinking that maybe I am supposed to do some DBus cleanup? Or am I missing some nuance of Hexchat plugin system? If I try the same with regular Python code outside the plugin system, both server and client exit just fine.

Fenikso
  • 9,251
  • 5
  • 44
  • 72
  • Honestly the DBus plugin is largely untested and unused so it very well may be a bug. – TingPing Nov 07 '16 at 18:35
  • @TingPing I am not following, what do you mean? I do not use any DBus plugin, I am writing a Python plugin for Hexchat, which tries to use python-dbus library as a client. What do you mean is untested and probably buggy? – Fenikso Nov 07 '16 at 20:17
  • The DBus support of HexChat. I haven't tested it or know anything more about it, just a thought. (I am the maintainer of HexChat) – TingPing Nov 08 '16 at 03:12
  • Also dbus-python is largely dead you should use Gio like this example: https://github.com/hexchat/hexchat/blob/master/src/common/dbus/example.py – TingPing Nov 08 '16 at 03:13
  • @TingPing The DBus support of HexChat is not what I am trying to use in this example / plugin (however it works well, I am using it somwhere else). Thanks for the Gio DBus example, I will try it. – Fenikso Nov 08 '16 at 08:05
  • So unfortunately, when I `from gi.repository import Gio` in HexChat plugin, the whole application freezes. The same happens with `import pydbus`. Anyway thanks for the pointers. – Fenikso Nov 08 '16 at 08:57
  • Oh sorry for whatever reason I misunderstood. Anyway yes pygobject is sadly incompat with HexChat. Also stop calling sleep() from a plugin. – TingPing Nov 08 '16 at 18:51

0 Answers0