You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多进程中while True循环停滞无报错,登录时长追踪功能异常

多进程登录时长追踪应用子进程停滞排查与解决

问题背景

开发的登录时长追踪应用此前运行正常,现出现子进程异常停滞问题。应用通过multiprocessing.Process()调用track_login_time函数,传入参数包括类对象parent、会话ID整数id,以及mp.Value('b', True)创建的父子进程共享变量shared_bool。

添加打印语句定位后,控制台仅输出:

Running.
Checking 1
Attempting 1

后续无任何输出,父进程正常运行,但子进程停滞,从未执行到parent.Interface.write()核心逻辑。已知shared_bool仅在logout函数中被设为False,当前未调用该函数;关闭dearpygui窗口时程序立即终止,推测子进程已提前终止。

排查与解决建议

1. 缩小共享变量锁的作用范围

代码中with shared_bool.get_lock()将后续所有逻辑都包裹在锁内,若父进程或其他进程持有该锁未释放,子进程会一直阻塞在锁等待环节。优化方式:

def track_login_time(parent, id, shared_bool):  # internal
    itn = 0
    print('Running.')
    while True:
        itn += 1
        print(f'Checking {itn}')
        time.sleep(1)
        # 仅在读取shared_bool.value时加锁
        with shared_bool.get_lock():
            keep_running = shared_bool.value
        if keep_running:
            print(f'Attempting {itn}')
            if itn % 10 == 0:
                print(f'Writing {itn}')
                current_time = datetime.now()
                session_time = current_time - parent.login_date
                write_data = [str(current_time), str(session_time)]
                parent.Interface.write([write_data], f'Logs!G{id+1}:H{id+1}', sheet_id=parent.vsid, silent=True)
        else:
            print('Exiting. 1')
            exit(12)
        if not dpg.is_dearpygui_running():
            print('Exiting. 2')
            exit(12)

同时排查父进程中操作shared_bool的代码,确认锁是否被正确释放。

2. 验证dearpygui跨进程状态判断有效性

dpg.is_dearpygui_running()在子进程中可能无法正确获取父进程的GUI状态,甚至引发阻塞。可以:

  • 暂时注释掉if not dpg.is_dearpygui_running():这段逻辑,测试子进程是否能正常循环输出;
  • 改用共享变量传递GUI运行状态,避免直接在子进程中调用dearpygui全局状态函数。

3. 检查类对象parent的跨进程兼容性

多进程中传递包含不可序列化资源(如网络连接句柄、GUI资源)的类对象,会导致子进程内对象状态异常甚至阻塞。优化方式:

  • 不直接传递parent对象,改为单独传入login_date、vsid等所需参数;
  • 在子进程中添加打印parent.Interface的状态,确认其在子进程中是否能正常初始化。

4. 捕获子进程异常输出

子进程可能抛出异常但未被捕获,导致静默终止。添加异常捕获逻辑:

def track_login_time(parent, id, shared_bool):  # internal
    try:
        itn = 0
        print('Running.')
        while True:
            itn += 1
            print(f'Checking {itn}')
            time.sleep(1)
            with shared_bool.get_lock():
                if shared_bool.value:
                    print(f'Attempting {itn}')
                    if itn % 10 == 0:
                        print(f'Writing {itn}')
                        current_time = datetime.now()
                        session_time = current_time - parent.login_date
                        write_data = [str(current_time), str(session_time)]
                        parent.Interface.write([write_data], f'Logs!G{id+1}:H{id+1}', sheet_id=parent.vsid, silent=True)
                else:
                    print('Exiting. 1')
                    exit(12)
                if not dpg.is_dearpygui_running():
                    print('Exiting. 2')
                    exit(12)
    except Exception as e:
        print(f'子进程异常: {type(e).__name__}: {e}')
        import traceback
        traceback.print_exc()
        exit(1)

同时可通过multiprocessing.Process的join()方法获取子进程退出码,确认是否异常终止。

5. 定位Attempting 1后的阻塞点

第一次循环itn=1不会触发write逻辑,但理论上应继续输出Checking 2。若没有后续输出,说明子进程在Attempting 1之后的代码中阻塞:

  • 在print(f'Attempting {itn}')后添加print(f'Post Attempting {itn}'),确认是否执行到该位置;
  • 检查parent.login_date是否为跨进程共享变量,若未正确同步可能导致读取阻塞。

内容的提问来源于stack exchange,提问作者BappoHotel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 03:35:38