Skip to content

Commit

Permalink
Add support for OpenImageIO default_thread_pool_shutdown() (#35)
Browse files Browse the repository at this point in the history
Adding support for calling default_thread_pool_shutdown() on
Windows. This should fix the hangs during shutdown that are
happening on that platform. This function is expected to be
included in the 2.5.3 release of OpenImageIO. This function
has also been backported to the Natron OpenImageIO MinGW
package on Windows and signalled via a
NATRON_OIIO_HAS_DEFAULT_THREAD_POOL_SHUTDOWN define.
  • Loading branch information
acolwell authored Jul 11, 2023
1 parent 2186287 commit b194c3c
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 68 deletions.
1 change: 1 addition & 0 deletions IO/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ OCIOPluginBase.o GenericOCIO.o $(OCIO_OPENGL_OBJS) \
ReadEXR.o WriteEXR.o \
ReadFFmpeg.o FFmpegFile.o WriteFFmpeg.o PixelFormat.o \
ReadOIIO.o WriteOIIO.o \
OIIOGlobal.o \
OIIOText.o \
OIIOResize.o \
ReadPFM.o WritePFM.o \
Expand Down
2 changes: 1 addition & 1 deletion OIIO/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PLUGINOBJECTS = ofxsThreadSuite.o tinythread.o \
ReadOIIO.o WriteOIIO.o \
ReadOIIO.o WriteOIIO.o OIIOGlobal.o \
OIIOText.o OIIOResize.o \
GenericReader.o GenericWriter.o GenericOCIO.o SequenceParsing.o \
ofxsOGLTextRenderer.o ofxsOGLFontData.o ofxsMultiPlane.o
Expand Down
90 changes: 90 additions & 0 deletions OIIO/OIIOGlobal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* ***** BEGIN LICENSE BLOCK *****
* This file is part of openfx-io <https://github.com/NatronGitHub/openfx-io>,
* (C) 2018-2023 The Natron Developers
* (C) 2013-2018 INRIA
*
* openfx-io is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* openfx-io is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with openfx-io. If not, see <http://www.gnu.org/licenses/gpl-2.0.html>
* ***** END LICENSE BLOCK ***** */
#include "OIIOGlobal.h"

#include "ofxsMacros.h"
#include <iostream>

#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#include <IlmThreadPool.h>
#endif

// clang-format off
GCC_DIAG_OFF(unused-parameter)
#include <OpenImageIO/imagecache.h>
#include <OpenImageIO/imageio.h>
GCC_DIAG_ON(unused-parameter)
// clang-format on

OIIO_NAMESPACE_USING

void
initOIIOThreads()
{
// See https://github.com/lgritz/oiio/commit/7f7934fafc127a9f3bc51b6aa5e2e77b1b8a26db
// We want OpenEXR to use all threads, while we do not want OIIO to use all threads for its image
// processing functionalities w/o letting the host know about it.
if (!attribute("exr_threads", 0)) {
// This version of OIIO does not have the exr_threads attribute, fallback on the "threads" attribute...
if (!attribute("threads", 0)) {
#ifdef DEBUG
std::cerr << "OIIO: Failed to set exr_threads and threads attribute" << std::endl;
#endif
}
#ifdef DEBUG
else {
std::cout << "Failed to set exr_threads to 0 fallback to OIIO threads=0" << std::endl;
}
#endif
} else {
// This version of OIIO has the exr_threads attribute. Set the "threads" attribute to limit image processing functions
static const int oiio_threads = 0;
#ifdef DEBUG
std::cout << "Successfully set exr_threads to 0, setting OIIO threads=" << oiio_threads << std::endl;
#endif
if (!attribute("threads", oiio_threads)) {
#ifdef DEBUG
std::cerr << "Failed to set the threads attribute for OIIO" << std::endl;
#endif
}
}
}

void
shutdownOIIOThreads()
{
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
// Kill all threads otherwise when the static global thread pool joins it threads there is a deadlock on Mingw
IlmThread::ThreadPool::globalThreadPool().setNumThreads(0);

// TODO: Remove the code in the following #if block once all platforms have been updated to an OpenImageIO
// version that defines default_thread_pool_shutdown().
#if NATRON_OIIO_HAS_DEFAULT_THREAD_POOL_SHUTDOWN != 1 && OIIO_VERSION < OIIO_MAKE_VERSION(2,5,3)
// Workaround to a bug: https://github.com/OpenImageIO/oiio/issues/1795
// see also https://github.com/LuxCoreRender/LuxCore/commit/607bfc9bff519ecc32c02ff3203b7ec71d201fde
OIIO::attribute("threads", 1);
#endif
#endif

// TODO: Remove #if once all platforms have been updated to an OpenImageIO version that defines
// default_thread_pool_shutdown().
#if NATRON_OIIO_HAS_DEFAULT_THREAD_POOL_SHUTDOWN == 1 || OIIO_VERSION >= OIIO_MAKE_VERSION(2,5,3)
default_thread_pool_shutdown();
#endif
}
46 changes: 3 additions & 43 deletions OIIO/OIIOGlobal.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* ***** BEGIN LICENSE BLOCK *****
* This file is part of openfx-io <https://github.com/NatronGitHub/openfx-io>,
* (C) 2018-2021 The Natron Developers
* (C) 2018-2023 The Natron Developers
* (C) 2013-2018 INRIA
*
* openfx-io is free software: you can redistribute it and/or modify
Expand All @@ -20,47 +20,7 @@
#ifndef IO_GLOBAL_OIIO_H
#define IO_GLOBAL_OIIO_H

#include "ofxsMacros.h"
#include <iostream>

// clang-format off
GCC_DIAG_OFF(unused-parameter)
#include <OpenImageIO/imageio.h>
GCC_DIAG_ON(unused-parameter)
// clang-format on

OIIO_NAMESPACE_USING

inline void
initOIIOThreads()
{
// See https://github.com/lgritz/oiio/commit/7f7934fafc127a9f3bc51b6aa5e2e77b1b8a26db
// We want OpenEXR to use all threads, while we do not want OIIO to use all threads for its image
// processing functionalities w/o letting the host know about it.
if (!attribute("exr_threads", 0)) {
// This version of OIIO does not have the exr_threads attribute, fallback on the "threads" attribute...
if (!attribute("threads", 0)) {
#ifdef DEBUG
std::cerr << "OIIO: Failed to set exr_threads and threads attribute" << std::endl;
#endif
}
#ifdef DEBUG
else {
std::cout << "Failed to set exr_threads to 0 fallback to OIIO threads=0" << std::endl;
}
#endif
} else {
// This version of OIIO has the exr_threads attribute. Set the "threads" attribute to limit image processing functions
static const int oiio_threads = 0;
#ifdef DEBUG
std::cout << "Successfully set exr_threads to 0, setting OIIO threads=" << oiio_threads << std::endl;
#endif
if (!attribute("threads", oiio_threads)) {
#ifdef DEBUG
std::cerr << "Failed to set the threads attribute for OIIO" << std::endl;
#endif
}
}
}
void initOIIOThreads();
void shutdownOIIOThreads();

#endif /* IO_GLOBAL_OIIO_H*/
14 changes: 2 additions & 12 deletions OIIO/ReadOIIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@
#include <set>
#include <sstream>

#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#include <IlmThreadPool.h>
#endif

#include "ofxsMacros.h"

#include "OIIOGlobal.h"
Expand Down Expand Up @@ -110,6 +106,7 @@ using namespace OFX::IO;
#ifdef OFX_IO_USING_OCIO
namespace OCIO = OCIO_NAMESPACE;
#endif
OIIO_NAMESPACE_USING

using std::make_pair;
using std::pair;
Expand Down Expand Up @@ -3146,14 +3143,7 @@ ReadOIIOPluginFactory::unload()
ImageCache::destroy(sharedcache);
#endif

#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
// Kill all threads otherwise when the static global thread pool joins it threads there is a deadlock on Mingw
IlmThread::ThreadPool::globalThreadPool().setNumThreads(0);

// Workaround to a bug: https://github.com/OpenImageIO/oiio/issues/1795
// see also https://github.com/LuxCoreRender/LuxCore/commit/607bfc9bff519ecc32c02ff3203b7ec71d201fde
OIIO::attribute("threads", 1);
#endif
shutdownOIIOThreads();
}

/** @brief The basic describe function, passed a plugin descriptor */
Expand Down
15 changes: 3 additions & 12 deletions OIIO/WriteOIIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "OIIOGlobal.h"
// clang-format off
GCC_DIAG_OFF(unused-parameter)
#include <OpenImageIO/imageio.h>
#include <OpenImageIO/filesystem.h>
GCC_DIAG_ON(unused-parameter)
// clang-format on
Expand All @@ -39,15 +40,12 @@ GCC_DIAG_ON(unused-parameter)
#include <ofxsCoords.h>
#include <ofxsMultiPlane.h>

#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#include <IlmThreadPool.h>
#endif

using namespace OFX;
using namespace OFX::IO;
#ifdef OFX_IO_USING_OCIO
namespace OCIO = OCIO_NAMESPACE;
#endif
OIIO_NAMESPACE_USING

using std::map;
using std::string;
Expand Down Expand Up @@ -1439,14 +1437,7 @@ mDeclareWriterPluginFactory(WriteOIIOPluginFactory, ;, false);
void
WriteOIIOPluginFactory::unload()
{
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
// Kill all threads otherwise when the static global thread pool joins it threads there is a deadlock on Mingw
IlmThread::ThreadPool::globalThreadPool().setNumThreads(0);

// Workaround to a bug: https://github.com/OpenImageIO/oiio/issues/1795
// see also https://github.com/LuxCoreRender/LuxCore/commit/607bfc9bff519ecc32c02ff3203b7ec71d201fde
OIIO::attribute("threads", 1);
#endif
shutdownOIIOThreads();
}

void
Expand Down

0 comments on commit b194c3c

Please sign in to comment.