为何在其他线程启动asyncio事件循环会导致Linux管道通信异常
异常成因分析
- 缓冲区未刷入管道:
subprocess.Popen创建的标准输入管道默认使用全缓冲策略,调用notify_proc.stdin.write()写入的hello\n首先会暂存在write进程的用户态缓冲区中,不会直接写入内核管道。未添加问题代码时,write.py执行完逻辑后进程直接退出,进程退出阶段会自动刷新所有缓冲区,数据就能顺利发送给read.py。添加问题代码后write进程持续存活,没有触发自动flush的时机,数据一直停留在缓冲区中,read.py根本收不到数据。 - 管道写端未关闭:创建的子线程默认
daemon属性为False,主线程执行完全部代码后会等待所有非守护线程退出才会终止整个进程。而子线程中的loop.run_forever()是永久阻塞调用,该线程永远不会退出,导致write进程持续运行,管道的写端文件描述符一直被进程持有、没有被关闭。read.py中的for line in sys.stdin会一直阻塞等待输入,直到收到管道写端关闭的EOF信号才会处理已接收的数据,因此不会产生任何输出。
修复方案
任选以下一种方案即可解决问题:
- 写入数据后手动刷新缓冲区,同时将子线程设为守护线程,主线程结束后直接终止进程:
# 创建线程时设置daemon=True thread = Thread(target=side_thread, args=(loop,), daemon=True) thread.start() notify_proc = subprocess.Popen("python read.py".split(), stdin=subprocess.PIPE) notify_proc.stdin.write("hello\n".encode("utf-8")) # 手动刷新缓冲区 notify_proc.stdin.flush()
- 写入完成后主动关闭管道写端,直接触发read.py的EOF信号:
notify_proc.stdin.write("hello\n".encode("utf-8")) notify_proc.stdin.close()
内容的提问来源于stack exchange,提问作者QuocAnh
相关产品推荐
相关产品推荐

