移除signal.signal(SIGCHLD,SIG_IGN)的影响及代码修改建议咨询
问题分析与修改建议
核心问题原因
设置signal.signal(signal.SIGCHLD, signal.SIG_IGN)后,内核会直接回收退出的子进程,导致subprocess.check_output无法获取子进程的退出状态码,因此无法判断子进程是否执行失败,自然不会触发CalledProcessError异常,你的try-except块也就无法生效。
修改方案
1. 移除SIGCHLD忽略语句
直接删除主函数中的这行代码:
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
移除后,subprocess.check_output就能正常获取子进程的退出状态,当子进程返回非0退出码时,会正确抛出CalledProcessError,你的错误处理逻辑即可正常工作。
2. 无需担心僵尸进程
你不必顾虑僵尸进程问题,因为subprocess.check_output内部会自动等待子进程结束,并调用wait()获取返回码,这个过程会直接回收子进程资源,不会产生僵尸进程。之前开发者添加的SIG_IGN属于冗余操作,在当前代码逻辑下完全没有必要。
3. 修复代码遗漏的导入
Worker类中使用了os.environ但未导入os模块,需要在代码顶部补充:
import os
修正后的完整代码示例
import threading import logging import queue import subprocess import signal import os # 新增导入 class Worker(threading.Thread): def __init__(self, thread_id, work_queue): threading.Thread.__init__(self) self._thread_id = thread_id self._queue = work_queue def run(self): while not self._queue.empty(): module = self._queue.get() os.environ["CUDA_VISIBLE_DEVICES"] = str(self._thread_id) try: subprocess.check_output(["python3.8", module]) except subprocess.CalledProcessError as e: logging.error( "Worker: {} failed to process '{}'. Error: {}".format( self._thread_id, module.split("/")[-1], e)) self._queue.task_done() logging.info("Worker: {} has exited!".format(self._thread_id)) def process_modules(modules): modulesQueue = queue.Queue() for i in modules: modulesQueue.put(i) workers = [] gpu_allocator = BaseGPUAllocator() for i in range(gpu_allocator.avail_gpu_card_number()): worker = Worker(i, modulesQueue) # 为每个可用GPU创建Worker workers.append(worker) worker.start() # 启动Worker线程 modulesQueue.join() # 等待所有任务处理完成 def validate_models(): modules = ["case1", "case2"] process_modules(modules) return modules if __name__ == "__main__": validate_models()
内容的提问来源于stack exchange,提问作者Johnzy
相关产品推荐
相关产品推荐

