Skip to content

Commit 17562fc

Browse files
committed
Add IECORE_RTLD_GLOBAL environment variable
This can be used to turn off the use of the `RTLD_GLOBAL` flag in Python, which makes us less vulnerable to symbol clashes between libraries. Updated CI to run the unit tests with it turned off.
1 parent 91dd6a8 commit 17562fc

File tree

3 files changed

+22
-14
lines changed

3 files changed

+22
-14
lines changed

.github/workflows/main.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ jobs:
164164
- name: Test
165165
run: |
166166
scons ${{ matrix.tests }} BUILD_TYPE=${{ matrix.buildType }} OPTIONS=${{ matrix.options }} CXXSTD=c++14 BUILD_CACHEDIR=sconsCache
167+
env:
168+
IECORE_RTLD_GLOBAL: 0
167169
# We have some work to do before we can run the tests
168170
# successfully on Windows. Until then, we satisfy ourselves
169171
# with checking that it at least _builds_.

.github/workflows/main/options.posix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ APPLESEED_LIB_PATH = deps + "/appleseed/lib"
6666
# Environment
6767
# ===========
6868

69-
ENV_VARS_TO_IMPORT = "PATH"
69+
ENV_VARS_TO_IMPORT = "PATH IECORE_RTLD_GLOBAL"
7070

7171
if platform.system() == "Darwin" :
7272
os.environ["DYLD_FRAMEWORK_PATH"] = libs

python/IECore/__init__.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,27 @@
3838
#
3939
# Some parts of the IECore library are defined purely in Python. These are shown below.
4040

41-
# Turn on RTLD_GLOBAL to avoid the dreaded cross module RTTI
42-
# errors on Linux. This causes libIECore etc to be loaded into
43-
# the global symbol table and those symbols to be shared between
44-
# modules. Without it, different python modules and/or libraries
45-
# can end up with their own copies of symbols, which breaks a
46-
# great many things.
47-
#
48-
# We use the awkward "__import__" approach to avoid importing sys
49-
# and ctypes into the IECore namespace.
50-
51-
if __import__( "os" ).name == 'posix':
52-
__import__( "sys" ).setdlopenflags(
53-
__import__( "sys" ).getdlopenflags() | __import__( "ctypes" ).RTLD_GLOBAL
41+
import os, sys, ctypes
42+
if os.name == "posix" and os.environ.get( "IECORE_RTLD_GLOBAL", "1" ) == "1" :
43+
# Historically, we had problems with cross-module RTTI on Linux, whereby
44+
# different Python modules and/or libraries could end up with their own
45+
# copies of symbols, which would break things like dynamic casts. We worked
46+
# around this by using RTLD_GLOBAL so that everything was loaded into the
47+
# global symbol table and shared, but this can cause hard-to-diagnose
48+
# knock-on effects from unwanted sharing.
49+
#
50+
# We now manage symbol visibility properly so that RTTI symbols should not
51+
# be duplicated between modules, and we intend to remove RTLD_GLOBAL. To aid
52+
# the transition, this behaviour can be controlled by the
53+
# `IECORE_RTLD_GLOBAL` environment variable, which currently defaults on.
54+
## \todo Get everything tested, default to off, and then remove.
55+
sys.setdlopenflags(
56+
sys.getdlopenflags() | ctypes.RTLD_GLOBAL
5457
)
5558

59+
# Remove pollution of IECore namespace
60+
del os, sys, ctypes
61+
5662
__import__( "imath" )
5763

5864
from ._IECore import *

0 commit comments

Comments
 (0)