8 Star 0 Fork 30

src-openEuler/libdnf

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
backport-python-bindings-Load-all-modules-with-RTLD_GLOBAL.patch 3.44 KB
一键复制 编辑 原始数据 按行查看 历史
chenhaixing 提交于 2024-01-02 09:03 . sync upstream patch
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)
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/src-openeuler/libdnf.git
git@gitee.com:src-openeuler/libdnf.git
src-openeuler
libdnf
libdnf
master

搜索帮助