-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
fix: guard C extension reload in _prefer_module_from_site_packages to prevent process crash #9148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -619,10 +619,34 @@ def _is_module_loaded_from_site_packages( | |||||||||||||
| return False | ||||||||||||||
|
|
||||||||||||||
|
|
||||||||||||||
| def _has_loaded_c_extension(module_name: str) -> bool: | ||||||||||||||
| """检查 sys.modules 中目标模块的依赖子树是否已包含 C 扩展。 | ||||||||||||||
|
|
||||||||||||||
| 遍历已加载的 key(如 'pikepdf'、'pikepdf._core'), | ||||||||||||||
| 检查其 __file__ 后缀是否为 .pyd / .so。 | ||||||||||||||
| """ | ||||||||||||||
| for key in list(sys.modules.keys()): | ||||||||||||||
| if not (key == module_name or key.startswith(f"{module_name}.")): | ||||||||||||||
| continue | ||||||||||||||
| mod = sys.modules.get(key) | ||||||||||||||
| if mod is None: | ||||||||||||||
| continue | ||||||||||||||
| mod_file = getattr(mod, "__file__", "") or "" | ||||||||||||||
| if os.path.splitext(mod_file)[1].lower() in (".pyd", ".so"): | ||||||||||||||
| return True | ||||||||||||||
|
Comment on lines
+634
to
+636
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 为了使 C 扩展检测更加健壮和具有防御性,我们应该显式检查
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Verified against the live AstrBot process: every module in |
||||||||||||||
| return False | ||||||||||||||
|
|
||||||||||||||
|
|
||||||||||||||
| def _prefer_module_from_site_packages( | ||||||||||||||
| module_name: str, site_packages_path: str | ||||||||||||||
| ) -> bool: | ||||||||||||||
| with _SITE_PACKAGES_IMPORT_LOCK: | ||||||||||||||
| if _has_loaded_c_extension(module_name): | ||||||||||||||
| logger.debug( | ||||||||||||||
| "Skipping prefer for %s: C extension detected in submodules", | ||||||||||||||
| module_name, | ||||||||||||||
| ) | ||||||||||||||
| return False | ||||||||||||||
| base_path = os.path.join(site_packages_path, *module_name.split(".")) | ||||||||||||||
| package_init = os.path.join(base_path, "__init__.py") | ||||||||||||||
| module_file = f"{base_path}.py" | ||||||||||||||
|
|
@@ -646,6 +670,8 @@ def _prefer_module_from_site_packages( | |||||||||||||
| if spec is None or spec.loader is None: | ||||||||||||||
| return False | ||||||||||||||
|
|
||||||||||||||
| # 已在 _has_loaded_c_extension 中扫描过——此处收集 matched_keys | ||||||||||||||
| # 仅用于 pop 和异常恢复,不再重复检测 C 扩展 | ||||||||||||||
| matched_keys = [ | ||||||||||||||
| key | ||||||||||||||
| for key in list(sys.modules.keys()) | ||||||||||||||
|
|
||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.