You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Ubuntu 20中STDIN重定向至FIFO的异常问题(Ubuntu 18可正常运行)

Ubuntu 20中STDIN重定向至FIFO的异常问题(Ubuntu 18可正常运行)

我来梳理下你遇到的问题和最终解决思路,帮其他碰到类似情况的开发者避坑:

问题场景与异常现象

你有一个C++应用,通过命名管道(FIFO)重定向STDIN作为输入源,同时将STDOUT输出到日志文件,这套逻辑在Ubuntu 18上运行完全正常,但切换到Ubuntu 20后出现了奇怪的异常:

  • 启动应用的命令:
    ./my_app 0</home/user/pipe 1> log.txt &
    
  • printf向FIFO发送指令:
    printf "ins\n" > /home/user/pipe
    
  • 应用内部用std::getline在try-catch块中读取输入,Ubuntu 18下能正常接收所有指令,但Ubuntu 20中读完第一条指令后,eofbitfailbit就会被永久触发,后续发送的指令完全无法读取。

你的完整启动脚本大致如下:

#!/bin/bash

./my_app 0</home/user/pipe 1> log.txt &

sleep 1

printf "ins1\n" > /home/user/pipe

sleep 5

printf "ins2\n" > /home/user/pipe

...

问题核心原因

本质是FIFO的特性导致的:当FIFO的所有写入端都关闭时,读取端会立刻收到EOF信号。在Ubuntu 20中,每次执行printf "xxx" > /home/user/pipe后,这个临时进程会立刻关闭FIFO的写入端,你的C++应用读完第一条指令后就触发了EOF,导致std::getline设置了错误位,后续即使重新打开FIFO写入,应用也无法恢复读取状态了。而Ubuntu 18的FIFO处理逻辑相对宽松,或者你的应用在旧版本下的错误位处理逻辑不同,才没有出现这个问题。

已验证的解决办法

你找到的方案非常关键:保持FIFO的一个写入端始终处于打开状态,这样就不会触发意外的EOF。具体操作是在启动应用前执行:

sleep infinity > /home/user/pipe &

这个sleep infinity进程会一直占用FIFO的写入端,后续每次printf只是新增一个临时写入端,执行完关闭后,还有这个sleep进程的写入端保持打开,你的C++应用就不会收到EOF信号,能持续读取后续发送的指令。最后在脚本结束时记得杀掉这个sleep进程即可。

备注:内容来源于stack exchange,提问作者dma

火山引擎 最新活动