solaris - solaris:在标准输入上设置的 O_NDELAY:当进程退出时,shell 退出
问题描述
TLDR:在 Solaris中,如果被子进程O_NDELAY
设置为 on stdin
,则退出。为什么?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
(类似于在 Linux 上),如下所示:csh
truss
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 尝试读取stdin
它时,它返回 0 导致它假设 EOF 被击中。
此页面指示O_NDELAY
不应再使用,而是推荐O_NONBLOCK
. 我发现了关于O_NDELAY
/FIONBIO
用于各种风格的 UNIX 的类似声明。
顺便说一句,在 LinuxO_NDELAY == FNDELAY == O_NONBLOCK
中,我无法在那个环境中重现这个问题也就不足为奇了。
不幸的是,执行此操作的工具不是我拥有源代码的工具,尽管从我的实验中我找到了解决该问题的方法。
如果没有别的,我可以制作一个O_NDELAY
像上面那样删除的简单程序,然后将这个工具的执行包装在一个 shell 脚本中,该脚本总是在另一个之后运行“修复程序”程序。
推荐阅读
- python - 在 Python 中操作列表中的一些值
- autohotkey - 为什么我的代码在最后打印双“k”?自动热键 (ahk)
- c# - 将光标移动到下一行,使其与上一行的最后一个字符对齐
- express - VueJS 不会显示来自 Express API 的数据
- python - 为什么使用 Python 2 打印 scapy.layers.l2.Ether 对象我得到了预期的结果,而使用 Python 3 打印它我得到了这个奇怪的输出?
- typescript - 将类型定义委托给实现
- java - 将char数组中的元素切换到int数组java中的相应位置
- ios - 将变量传递给 LocationManagerDelegate 类
- python - 特定格式的字符串
- reactjs - 当我单击删除按钮时,列表中的顶部项目将被删除。我该如何解决?