RPC plugin API for enabling out-of-process (OOP) plugins #452

Arnavion opened this Issue Mar 15, 2013 · 2 comments


None yet
1 participant

Arnavion commented Mar 15, 2013


  1. A new plugin rpc.dll that exposes all the plugin API (init, hook_*, etc.) as RPC endpoints. (See last section for implementation details.)
  2. Change the Python plugin into two files:
    • python-rpc.exe that contains the current Python plugin's code, i.e., it exposes the hexchat_* API for scripts to use. The difference is that the API works by forwarding calls over RPC to rpc.dll's endpoints.
    • python-rpc.dll, the plugin loaded by Hexchat. This does nothing except start python-rpc.exe.
  3. Similar for Perl, but I'll focus on Python first because its plugin code looks simpler.


(in order of decreasing importance)

  1. Freedom from threading issues in the plugins. Plugins can call the RPC API from any thread they want, because all the calls will become serialized in Hexchat. This will for example allow Python scripts to use threads.
  2. If a plugin crashes or hangs, it doesn't take down Hexchat.
  3. Existing C plugins will work unchanged because they will still be loaded in-process and use the original API. Existing Python and Perl scripts will work unchanged because they will transparently use the RPC API.
  4. No more MSVCRT hell in the main Hexchat process. (There's still MSVCRT hell in the *-rpc.exe processes, so only a minor benefit.)
  5. Allows out-of-process plugins and external applications in general to interact with Hexchat.


(in order of decreasing importance)

  1. This will allow arbitrary processes to act as Hexchat plugins. This is not a security concern, since plugins/scripts are already stored in and loaded from user-writable space, but we'll probably want to extend the plugins and scripts GUI to let the user specify which OOP plugins he wants to allow and save this list. This is not complete protection of course since a malicious plugin can still impersonate an accepted plugin. However, I am not aware of any malware which has tried to inject scripts into Hexchat so I'm not concerned about this event; if any such malware exists, please let me know.
  2. If an OOP plugin crashes or hangs, Hexchat (and thus the user) have no way of knowing this.
  3. Scripts written specifically against the RPC API (for example, Python scripts which expect to be able to use threads) will not be backward-compatible with versions of Hexchat that don't have rpc.dll. (Not a concern since we always want users to upgrade to the latest Hexchat.)


  1. I initially thought of making this Windows-only (using Windows RPC API).
    But if there is interest in making this cross-platform, we would have to consider GDbus. (Ugh.)
  2. There is no reason to keep rpc.dll as a plugin; it can also be made in-built. I thought of making it a plugin because users may not want to install it because of disadvantage point 1.

Some rather complicated rearchitecting is required, so this is not necessarily going to be ready any time soon. I'm filing this issue just to get dev/community feedback. Thoughts?


Arnavion commented Mar 15, 2013

Updates after talking about it with TingPing:

  1. Existing code in src/common/dbus already has a DBus implementation. Just need to combine it with python.c to make python-rpc.exe
  2. Dis 1 isn't a big deal, so misc 2 isn't necessary. We can have rpc.dll built-in to Hexchat instead of a plugin. This also means script writers don't have to worry that some of the users will be running the script in a non-RPC plugin host.
  3. Clarification of the system
[             ]o <----------      ----------> o[ python-rpc.exe (script1.py) (script2.py) ]
| hexchat.exe |o <---------- DBUS ----------> o[ perl-rpc.exe (script1.pl) (script2.pl) ]
[             ]o <----------      ----------> o[ third-party-application.exe ]

python-rpc.exe is essentially what python.c is right now, except that it's not an Hexchat C plugin. For example, instead of implementing xchat.prnt by calling hexchat_print, it insteads uses DBus to tell hexchat.exe to call hexchat_print.
Third-party applications will use their own DBus infrastructure to talk to Hexchat directly; they will not go via the *-rpc.exe's. The *-rpc.exe's are only for hosting scripts.

  1. While the two *-rpc.exe don't need to expose an unload/unregister API to scripts, such an API is necessary for third-party applications.
  2. I don't want to have any sort of constant polling of the plugins to see if they're hung or not, so I'm still thinking of a way to detect hung plugins.

There are four types of interactions Hexchat has with a plugin:

  1. Two-way hexchat -> plugin. For example, an event hook. Hexchat posts a message to the plugin and must wait for the plugin to respond.
  2. One-way hexchat -> plugin. For example, a timer hook. Hexchat posts a message to the plugin but doesn't need to wait for the plugin to respond.
  3. Two-way plugin -> hexchat. For example, xchat.get_prefs(). Plugin posts a message to Hexchat and waits for Hexchat's response.
  4. One-way plugin -> hexchat. For example, xchat.prnt(). Plugin posts a message to Hexchat but doesn't need to wait for Hexchat to respond.

Of these, the only case where a hung plugin will affect Hexchat negatively is the first one. Perhaps we can work around that by using a timer?

Arnavion was assigned Mar 29, 2013


Arnavion commented Mar 29, 2013

See new issue.

Arnavion closed this Mar 29, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment