如何让嵌入式CPython初始化时不操作stdio以避免线程阻塞问题
如何让嵌入式CPython初始化时不操作stdio以避免线程阻塞问题
嘿,我之前碰到过几乎一模一样的问题!CPython在嵌入式初始化阶段,确实会偷偷对标准IO做不少隐式操作——比如初始化全局缓冲结构、获取CRT的IO同步锁,刚好你的线程在同时读取stdin,两边抢同一套IO资源直接就死锁了。
要解决这个问题,核心就是明明白白告诉CPython别碰系统原生的stdio流,反正你也说了嵌入式里的Python代码完全用不上stdio,刚好可以这么干。
直接上可落地的解决方案,修改你的PyConfig配置就行:
在PyConfig_InitIsolatedConfig(&config);之后,添加几行配置,把CPython要用到的标准文件描述符设为无效值:
// 告诉CPython不要使用系统的stdin/stdout/stderr,直接设为无效的文件描述符 config.stdio_fd[0] = -1; // 禁用stdin config.stdio_fd[1] = -1; // 禁用stdout config.stdio_fd[2] = -1; // 禁用stderr(如果需要保留Python的错误输出,可以只注释这行)
这样CPython初始化的时候,就不会去尝试打开或操作原来的stdin了,自然也就不会和你的读取线程抢资源导致死锁。
如果你担心设为-1在某些旧版本CPython上有兼容性问题,还有个备选方案:把标准流重定向到空设备。比如在Windows上,你可以打开NUL设备,把它的文件描述符给CPython用:
// Windows下打开NUL设备 HANDLE nul_handle = CreateFileA("NUL", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (nul_handle != INVALID_HANDLE_VALUE) { int nul_fd = _open_osfhandle((intptr_t)nul_handle, _O_RDWR); config.stdio_fd[0] = nul_fd; config.stdio_fd[1] = nul_fd; config.stdio_fd[2] = nul_fd; }
不过这个需要后续手动处理文件描述符的关闭,不如直接设-1清爽,所以优先推荐第一种方法。
另外补个小细节:你已经把Windows的stdio设为二进制模式了,本来CPython初始化时可能会偷偷改回文本模式,现在这么配置后也完全不用担心了——因为它根本碰不到原来的stdio流。
最后再确认下:这么修改后,你的读取线程可以正常跑,CPython初始化也不会卡,完美解决你的问题。
备注:内容来源于stack exchange,提问作者glukoz
相关产品推荐
相关产品推荐

