Skip to content

Commit dd6afb9

Browse files
committed
fix: load gopy extensions with RTLD_LOCAL to prevent Go runtime interposition
On macOS, Python's default dlopen flags are RTLD_NOW|RTLD_GLOBAL (Py_RTLD_DEFAULT in configure.ac for Darwin). Every .so extension imported via the normal Python import machinery is therefore loaded into the process-wide flat namespace. When two gopy extensions are loaded in the same process, the second extension's Go runtime symbols (TLS keys, mheap_, cgo init pointers) get interposed by the first extension's definitions, causing the two independent Go runtimes to share GC state and triggering 'fatal error: bad sweepgen in refill' (issue #385). The generated Python wrapper now temporarily clears RTLD_GLOBAL before importing the underlying _<pkg>.so, so each extension's Go runtime keeps its own isolated copy of these globals. The original flags are restored immediately after import so the rest of the program is unaffected.
1 parent 5072ba0 commit dd6afb9

1 file changed

Lines changed: 15 additions & 0 deletions

File tree

bind/gen.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,22 @@ except ImportError:
317317
cwd = os.getcwd()
318318
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
319319
os.chdir(currentdir)
320+
# Load the extension with RTLD_LOCAL so each gopy .so keeps its own copy of
321+
# the Go runtime globals (mheap_, TLS keys, etc.). On macOS, Python's default
322+
# dlopen flags include RTLD_GLOBAL which causes symbol interposition across
323+
# independently-built Go runtimes loaded in the same process (issue #385).
324+
if hasattr(sys, 'getdlopenflags'):
325+
try:
326+
import ctypes as _gopy_ctypes
327+
_gopy_saved_flags = sys.getdlopenflags()
328+
sys.setdlopenflags(_gopy_saved_flags & ~getattr(_gopy_ctypes, 'RTLD_GLOBAL', 0))
329+
except Exception:
330+
_gopy_saved_flags = None
331+
else:
332+
_gopy_saved_flags = None
320333
%[6]s
334+
if _gopy_saved_flags is not None:
335+
sys.setdlopenflags(_gopy_saved_flags)
321336
os.chdir(cwd)
322337
323338
# to use this code in your end-user python file, import it as follows:

0 commit comments

Comments
 (0)