Skip to content

Commit

Permalink
Work around thread-safety issue deep inside RSVG+Cairo.
Browse files Browse the repository at this point in the history
Running the rendering in multiple threads will crash. Work around
it by placing a mutex around it.
  • Loading branch information
hzeller committed Jan 15, 2024
1 parent e362f03 commit 8d5bb57
Showing 1 changed file with 26 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/svg-image-source.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,23 @@

#include "framebuffer.h"

// There is a thread-safety issue with RSVG + Cairo that manifests
// as we LoadAndScale() in a thread-pool.
// Typically crashing at _cairo_ft_scaled_glyph_load_glyph in the
// call stack of rsvg_handle_render_document().
//
// Workaound: add a global mutex around rsvg_handle_render_document(), which
// fixes it.
//
// TODO: figure out what the issue is, file bug upstream and make this
// macro dependent on Cairo and RSVG Version macros if it is known which
// version fixed it.
#define RSVG_THREADSAFE_ISSUE 1

#if RSVG_THREADSAFE_ISSUE
# include <mutex>
#endif

namespace timg {

std::string SVGImageSource::FormatTitle(
Expand Down Expand Up @@ -83,8 +100,17 @@ bool SVGImageSource::LoadAndScale(const DisplayOptions &opts, int, int) {
.height = orig_height_,
};

#if RSVG_THREADSAFE_ISSUE
static std::mutex render_mutex;
render_mutex.lock();
#endif

bool success = rsvg_handle_render_document(svg, cr, &viewport, nullptr);

#if RSVG_THREADSAFE_ISSUE
render_mutex.unlock();
#endif

cairo_destroy(cr);
cairo_surface_destroy(surface);
g_object_unref(svg);
Expand Down

0 comments on commit 8d5bb57

Please sign in to comment.