TLDR:在Solaris中,如果子进程在stdin
上设置了O_NDELAY
,则bash
将退出。为什么?
以下代码导致交互式bash
(v4.3.33(或tcsh
(6.19.00(shell在进程完成运行后退出:
#include <fcntl.h>
int main() {
fcntl( 0, F_SETFL, O_NDELAY );
//int x = fcntl( 0, F_GETFL );
//fcntl( 0, F_SETFL, ~(x ^ (~O_NDELAY)) );
return 0;
}
我们的ksh
、csh
和zsh
版本不受此问题的影响。
为了调查,我运行了bash
&truss
下的csh
(类似于Linux上的strace
(如下:
$ truss -eaf -o bash.txt -u'*' -{v,r,w}all bash --noprofile --norc
$ truss -eaf -o csh.txt -u'*' -{v,r,w}all csh -f
csh
完成进程运行后,将执行以下操作:
fcntl( 0, F_GETFL ) = FWRITE|FNDELAY
fcntl( 0, F_SETFL, FWRITE) = 0
这给了我一个主意。我将程序更改为上面注释掉的代码,以便切换O_NDELAY
的状态。如果我连续运行两次,bash不会退出。
read
(在Solaris中(的手册页显示:
When attempting to read a file associated with a terminal that has no data currently available:
* If O_NDELAY is set, read() returns 0
* If O_NONBLOCK is set, read() returns -1 and sets errno to EAGAIN
因此,当bash尝试读取CCD_ 16时,它返回0,导致它认为EOF被命中。
此页面表示不应再使用O_NDELAY
,而应推荐使用O_NONBLOCK
。对于各种风格的UNIX,我发现了关于O_NDELAY
/FIONBIO
的类似语句。
顺便说一句,在LinuxO_NDELAY == FNDELAY == O_NONBLOCK
中,我无法在那个环境中重现这个问题也就不足为奇了。
不幸的是,做这件事的工具不是我的源代码,尽管通过我的实验,我找到了解决这个问题的方法。
如果没有其他东西,我可以制作一个简单的程序,如上所述删除CCD_;定影器";一个接一个的程序。