为什么管道输入对 zenity 没问题,但 <文件故障?

Pet*_*r.O 3 pipe io-redirection zenity

我的问题就像zenity --text示例中的args 所说的一样简单……但是是什么导致了重定向对 CPU 的 100% 占用?
...(顺便说一句,这种特殊的用法是<实际调用的redirection。它似乎是在创建一个方向,而不是重新定向)。

echo "Peacocks talking of the colour grey."> test
cat test | zenity --text='This does NOT hog the CPU'   --list --column='#' --width=450 
<test      zenity --text='This hogs 100% of CPU usage' --list --column='#' --width=450
 
Run Code Online (Sandbox Code Playgroud)

我很高兴使用cat test |(因为在这种情况下它并不是没用;它可以工作并且 < 并且|在某种程度上有所不同,但我无法再次追踪它......

需要明确的是:<testcat test |两个工作。在这两种情况下,zenity 对话框都会出现并且功能齐全,但是只要<test对话框的版本保持打开状态,它就会使用 100% CPU(一个核心)......在单个“核心”VM 上使用 94%。 .

cam*_*amh 5

它看起来像是 zenity 中的一个错误。您可以使用该strace工具查看正在发生的事情(我在这篇文章中包装了 strace 行以使其更易于阅读)。

对于管道版本,strace 中的这一行显示了管道关闭(因为cat退出)时会发生什么:

poll([{fd=4, events=POLLIN}, {fd=3, events=POLLIN}, {fd=0, events=POLLIN}], \
     3, 0) = 1 ([{fd=0, revents=POLLIN|POLLHUP}])
Run Code Online (Sandbox Code Playgroud)

最后的那部分 -fd=0, revents=POLLIN|POLLHUP尤其是POLLHUP- 告诉 zenity stdin 挂了(管道的作者已经走了)。Zenity 正在正确处理此问题并稍后关闭 fd 0。

文件不会获取POLLHUP事件 - 相反,read(2)结果为零意味着 EOF。这是 zenity 的不同代码路径。它再次轮询 fd 0,结果如下:

poll([{fd=4, events=POLLIN}, {fd=3, events=POLLIN}, {fd=0, events=POLLIN}],\
     3, 0) = 1 ([{fd=0, revents=POLLIN}])
read(0, "", 1024)       = 0
Run Code Online (Sandbox Code Playgroud)

这应该是它的结束 - 零读取应该导致 zenity 关闭 fd 0。但事实并非如此。上面的 strace 输出不断重复,因为 zenity 不断轮询 fd 0。在 fd 0 关闭之前,它将始终准备好读取,因为这就是 EOF 的文件描述符的工作方式,因为您需要读取它以获得 EOF 结果。

因为 zenity 没有正确响应 stdin 上的 EOF,它一直在poll(2)/循环上read(2)循环,在那里poll立即返回,就像read. 一次,一次又一次……