From 68041232440ae877df98adb0f460426d209b9c4a Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Tue, 16 Jul 2019 16:25:08 -0700 Subject: [PATCH] modules/media/magick: Synchronize module unload. --- modules/media/magick.cc | 46 +++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/modules/media/magick.cc b/modules/media/magick.cc index cdb331c54..901353e53 100644 --- a/modules/media/magick.cc +++ b/modules/media/magick.cc @@ -32,6 +32,9 @@ namespace ircd::magick static void init(); static void fini(); + extern bool call_ready; + extern ctx::dock call_dock; + extern ctx::mutex call_mutex; extern conf::item limit_ticks; extern conf::item limit_cycles; extern conf::item yield_threshold; @@ -96,6 +99,20 @@ ircd::magick::yield_interval { "default", 768L }, }; +// It is likely that we can't have two contexts enter libmagick +// simultaneously. This race is possible if the progress callback yields +// and another context starts an operation. It is highly unlikely the lib +// can handle reentrancy on the same thread. Hitting thread mutexes within +// magick will also be catastrophic to ircd::ctx. +decltype(ircd::magick::call_mutex) +ircd::magick::call_mutex; + +decltype(ircd::magick::call_dock) +ircd::magick::call_dock; + +decltype(ircd::magick::call_ready) +ircd::magick::call_ready; + decltype(ircd::magick::version_api) ircd::magick::version_api { @@ -148,6 +165,9 @@ ircd::magick::init() ::SetMonitorHandler(handle_progress); ::SetMagickResourceLimit(ThreadsResource, 1UL); + call_ready = true; + call_dock.notify_all(); + log::debug { log, "resource settings: pixel max:%lu:%lu height:%lu:%lu width:%lu:%lu; threads:%lu:%lu", @@ -170,6 +190,12 @@ ircd::magick::fini() "Shutting down Magick Library..." }; + call_ready = false; + call_dock.wait([] + { + return !call_mutex.locked(); + }); + ::DestroyMagickResources(); ::DestroyMagick(); } @@ -399,12 +425,6 @@ ircd::magick::display::display(const ::ImageInfo &info, namespace ircd::magick { - // It is likely that we can't have two contexts enter libmagick - // simultaneously. This race is possible if the progress callback yields - // and another context starts an operation. It is highly unlikely the lib - // can handle reentrancy on the same thread. Hitting thread mutexes within - // magick will also be catastrophic to ircd::ctx. - ctx::mutex call_mutex; } template(a)..., &ei) @@ -464,11 +491,18 @@ return_t ircd::magick::call(function&& f, args&&... a) { + if(unlikely(!call_ready)) + throw error + { + "Graphics library not ready." + }; + const std::lock_guard lock { call_mutex }; + assert(call_ready); return f(std::forward(a)...); }