-
Pl
chevron_right
Christian Hergert: Asynchronous Varlink with varlink-glib
news.movim.eu / PlanetGnome • 8:55 • 2 minutes
I’ve been putting together
varlink-glib
, which is a library for writing Varlink clients and services in C. The basic idea is to keep the transport policy out of the library. You get a connected
GIOStream
however you want, whether that is GLib networking, socket activation, or something more specialized, and then wrap it in a
VarlinkClientProtocol
or
VarlinkServerProtocol
.
The API is built around
DexFuture
, which makes the async parts feel a lot nicer in C than the usual callback layering. Client calls return a future, server replies return a future, and internally the protocol can use fibers for the work that wants to look sequential while still integrating with the GLib main context. This is very much the style of API I want for system services: explicit enough that you can debug it, but not so painfully manual that every call site becomes a state machine.
future = example_calc_add_call_invoke (proxy,
call,
VARLINK_METHOD_CALL_DEFAULT,
add_reply_cb,
NULL,
NULL);
There is also a
varlink-codegen
tool which takes a
.varlink
interface and generates typed C wrappers for it. That gives you proxy objects, server skeletons, call objects, reply objects, and error constants instead of making every application hand-roll JSON. You can still drop down to
VarlinkMessage
,
VarlinkMessageBuilder
, and
VarlinkMessageReader
for forwarding or weird infrastructure cases, but most code should get to stay typed.
File descriptor passing works when the transport is a Unix socket connection. This follows the same general model as systemd’s Varlink support: the JSON payload contains an integer index, while the actual descriptors are sent out-of-band with
SCM_RIGHTS
and attached to the containing message as a
GUnixFDList
. Generated code can continue to treat the field as an integer, while the actual descriptor list stays attached to the underlying
VarlinkMessage
.
fd_list = g_unix_fd_list_new (); fd_index = g_unix_fd_list_append (fd_list, fd, &error); varlink_message_set_unix_fd_list (parameters, fd_list);
Protocol upgrades are supported too. A method call can ask to upgrade the connection, and once the final successful reply is sent, Varlink stops being valid on that connection. The
VarlinkProtocol
is still a
GIOStream
, so the next protocol can continue reading and writing through the same object. That keeps the handoff explicit without requiring a separate transport abstraction.
I also wired in optional Sysprof capture support. When enabled, client and server RPCs can show up as Sysprof marks with useful bits like method name, result, reply count, one-way, multi-reply, upgrade, Varlink error, and
GError
details. That matters because once you have concurrent calls, generated dispatch through
VarlinkServerRegistry
, and services doing real work, “it got slow somewhere” is not enough information.
There is still more polish to do, but the shape is there: typed generated APIs for normal users, low-level message APIs for infrastructure,
DexFuture
for async flow, Unix FD passing for the system service cases, protocol upgrades for handoff cases, and profiler hooks so it can be debugged when the happy path stops being happy.
A small personal note: as I wrote in my recent update from France , I am no longer employed by Red Hat. Work like this is currently self-funded, out of pocket, while my family and I settle into a new chapter. If you find it useful, a note of encouragement or a contribution means a lot right now. It helps make it possible to keep improving the free software infrastructure many of us rely on.