From c2f07e10cdd73adaed53137c92429cd44fdd58ae Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 22 Aug 2026 07:16:52 +0800 Subject: [PATCH] =?UTF-8?q?fix(tpc):=20worker=20cProfile=20=E4=B8=8E=20viz?= =?UTF-8?q?tracer=20=E4=BA=92=E6=96=A5=E2=80=94=E2=80=94=E5=A4=96=E9=83=A8?= =?UTF-8?q?=20profiler=20=E6=B4=BB=E8=B7=83=E6=97=B6=E8=B7=B3=E8=BF=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 冲突机制:viztracer --log_multiprocess 经 sys.setprofile 注入 profiler 到 worker,TPC _ProfileWorker 的 cProfile.enable() 检测到已激活 profiler 抛 'Another profiling tool is already active' -> worker 崩溃 -> batch 0 异常 -> 编译终止 - 修复:_ProfileWorker 先查 sys.getprofile(),非 None(viztracer 等外部 profiler 活跃)时跳过 cProfile 让 viztracer 独占;正常编译(无外部 profiler)仍保留 cProfile(PROF 数据不受影响) --- lib/Projectrans/Phase2Translator.py | 32 ++++++++++++++++++----------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/lib/Projectrans/Phase2Translator.py b/lib/Projectrans/Phase2Translator.py index c054ce9..4a7bf45 100644 --- a/lib/Projectrans/Phase2Translator.py +++ b/lib/Projectrans/Phase2Translator.py @@ -286,21 +286,29 @@ def _CleanProfFiles() -> None: def _ProfileWorker(_fn): @_functools.wraps(_fn) def _wrapper(*args, **kwargs): - _prof: cProfile.Profile = cProfile.Profile() - _prof.enable() + _prof = None try: + # 互斥:viztracer 等外部 profiler 已激活(sys.getprofile() 非 None)时 + # 跳过 cProfile——Python 只允许一个 profiling tool 同时活跃, + # cProfile.enable() 会抛 "Another profiling tool is already active" + # → worker 崩溃 → batch 异常 → 编译终止(viztracer --log_multiprocess 场景)。 + # 此时让 viztracer 独占记录,正常编译(无外部 profiler)仍保留 cProfile。 + if sys.getprofile() is None: + _prof = cProfile.Profile() + _prof.enable() return _fn(*args, **kwargs) finally: - _prof.disable() - _seq: int = getattr(_wrapper, '_seq', 0) + 1 - _wrapper._seq = _seq - try: - if not os.path.isdir(PROF_DIR): - os.makedirs(PROF_DIR, exist_ok=True) - _out: str = os.path.join(PROF_DIR, f'worker_prof_{os.getpid()}_{_seq}.prof') - _prof.dump_stats(_out) - except Exception: - pass + if _prof is not None: + _prof.disable() + _seq: int = getattr(_wrapper, '_seq', 0) + 1 + _wrapper._seq = _seq + try: + if not os.path.isdir(PROF_DIR): + os.makedirs(PROF_DIR, exist_ok=True) + _out: str = os.path.join(PROF_DIR, f'worker_prof_{os.getpid()}_{_seq}.prof') + _prof.dump_stats(_out) + except Exception: + pass return _wrapper