Minimal thread safety in cgraph

Hi,

It’s well established that libcgraph and friends aren’t thread-safe. That bug specifies that merely reading from multiple threads can be problematic.

Is it safe to use Graphviz in its own single thread of a multi-threaded program? (i.e. Graphviz itself nor its dependencies call thread-unsafe functions themselves)

With event-driven libraries like GLib+GTK frequently making threads in the background unbeknownst to the caller, it would otherwise be tricky to orchestrate a program that could use Graphviz safely without interprocess communication.

Back in the day I had graphviz wrapped up in a “string in”, “string out” function (DOT->SVG) where each call created its own “gvContextPlugins” instance, which I assumed was thread safe (It was inside an ActiveX + NAPI plugin - so may have been isolated at a higher level): GraphControl/libagraph.cpp at master · hpcc-systems/GraphControl (github.com).

If not a mutex around that call would protect it.

Is it safe to use Graphviz in its own single thread of a multi-threaded program? (i.e. Graphviz itself nor its dependencies call thread-unsafe functions themselves)

I think what you’re asking is if graphviz or its deps might read or mutate unsynchronized shared state. Maybe, maybe there are some shared buffers (maybe in libraries used by graphviz? Maybe in libc? Maybe in cairo?)

E.g. it would be bad if cairo had a shared unsynchronized mutable buffer, and if you called cairo from thread a while graphviz called cairo from thread b, you would have a data race.

Graphviz uses many libraries and I expect nobody has audited them for thread safety.

If i were you (depending on your constraints), I’d run graphviz as a separate process with its own address space. This also gives you crash isolation and security benefits. I understand this isn’t always an option though for interactive use.

Thread safety is really hard and i don’t think many programs handle it well. You could try confining graphviz to one thread and hoping that the deps don’t use shared buffers. It will likely depend if the rest of your code calls graphviz’s deps directly. You probably call some of graphviz’s deps directly e.g. libc, but (hopefully?) libc should be thread safe.

I know this is an unsatisfying answer, but i would assume it’s not 100% safe to use graphviz in a multithreading situation, even if you confine graphviz calls to a single thread. You’d have to audit a lot of dependencies to prove it was safe.

1 Like