Projects
Eulaceura:Factory
libdnf
_service:obs_scm:backport-python-bindings-Load-...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:backport-python-bindings-Load-all-modules-with-RTLD_GLOBAL.patch of Package libdnf
From 8a8548de607e0488fd4b8ab05373749545a29342 Mon Sep 17 00:00:00 2001 From: Mark Johnston <markj@FreeBSD.org> Date: Thu, 24 Aug 2023 17:43:36 -0400 Subject: [PATCH] python bindings: Load all modules with RTLD_GLOBAL libdnf's python bindings are implemented by a set of C++ shared objects generated by swig. Some generated code is duplicated between modules, in particular the SwigPyIterator class templates, which use exceptions of type swig::stop_iteration to signal an end-of-iteration condition. The modules do not depend on each other and thus belong to different DAGs from the perspective of the runtime linker. It turns out that this stop_iteration exception can be thrown between modules. This happens at least during dnf startup with python 3.9: cli.py(935): subst.update_from_etc(from_root, varsdir=conf._get_value('varsdir')) --- modulename: config, funcname: _get_value config.py(102): method = getattr(self._config, name, None) config.py(103): if method is None: config.py(105): return method().getValue() --- modulename: conf, funcname: varsdir conf.py(1183): return _conf.ConfigMain_varsdir(self) --- modulename: conf, funcname: getValue conf.py(512): return _conf.OptionStringList_getValue(self) --- modulename: substitutions, funcname: update_from_etc substitutions.py(47): for vars_path in varsdir: --- modulename: module, funcname: __iter__ module.py(557): return self.iterator() --- modulename: module, funcname: iterator module.py(555): return _module.VectorString_iterator(self) --- modulename: transaction, funcname: __next__ transaction.py(94): return _transaction.SwigPyIterator___next__(self) In particular, the module and transaction modules are somehow both involved: module returns the iterator, and transaction advances the iterator. Both modules contain the same iterator code, so I'm not sure why it works this way. The behaviour is sensitive to import order; for example, if transaction is imported before module, then the code above ends up using module's implementation of SwigPyItreator___next__. In any case, the use of swig::stop_iteration is broken in the above scenario since the exception is thrown by module with module.so's copy of the swig::stop_iteration type info, and caught by transaction.so using transaction.so's copy of the type info, resulting in an uncaught exception. Work around the problem by loading all modules with RTLD_GLOBAL to ensure that RTTI is unique. This is required when throwing exceptions across DSO boundaries, see https://gcc.gnu.org/faq.html#dso for example. Conflict:NA Reference:https://github.com/rpm-software-management/libdnf/commit/8a8548de607e0488fd4b8ab05373749545a29342 --- bindings/python/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bindings/python/__init__.py b/bindings/python/__init__.py index 3bfd3a9441..07cf1959d5 100644 --- a/bindings/python/__init__.py +++ b/bindings/python/__init__.py @@ -6,11 +6,14 @@ import sys, os sys.setdlopenflags(os.RTLD_NOW | os.RTLD_GLOBAL) from . import error -sys.setdlopenflags(os.RTLD_NOW) +# Other modules also need to be loaded with RTLD_GLOBAL to preserve uniqueness +# of RTTI. There are code paths where an exception thrown in one module is +# supposed to be caught in another. from . import common_types from . import conf from . import module from . import repo from . import transaction from . import utils +sys.setdlopenflags(os.RTLD_NOW)
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2