mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-10-31 20:34:48 +08:00
38 lines
1.4 KiB
Python
38 lines
1.4 KiB
Python
"""
|
|
free-threaded 运行时下插件触发 GIL 回退的归因。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable, Iterator
|
|
from contextlib import contextmanager
|
|
|
|
from app.foundation.environment import is_free_threaded_runtime, is_gil_enabled
|
|
|
|
# 按插件 ID 记录"该插件的加载使进程回退到 GIL"的端口,由注册表实现
|
|
GilFallbackRecorder = Callable[[str], None]
|
|
|
|
|
|
def ignore_gil_fallback(_plugin_id: str) -> None:
|
|
"""
|
|
默认归因端口:未装配注册表的加载器/生命周期不记录归因。
|
|
"""
|
|
|
|
|
|
@contextmanager
|
|
def attribute_gil_fallback(plugin_id: str, recorder: GilFallbackRecorder) -> Iterator[None]:
|
|
"""
|
|
观察包裹区间内 GIL 是否从关闭变为开启,发生时把回退归因到该插件。
|
|
|
|
GIL 一旦被原生扩展开启就会保持到进程结束,因此只有第一个触发转换的插件能被观察到;
|
|
之后加载的插件即使同样缺少 free-threaded 声明,也无法再被区分。
|
|
插件在加载之后才惰性导入的原生扩展不在任何包裹区间内,同样无法归因。
|
|
区间内抛出的异常照常向外传播,归因在 finally 中完成,加载失败的插件同样会被记录。
|
|
"""
|
|
gil_enabled_before = is_gil_enabled()
|
|
try:
|
|
yield
|
|
finally:
|
|
if is_free_threaded_runtime() and not gil_enabled_before and is_gil_enabled():
|
|
recorder(plugin_id)
|