简体   繁体   English

solaris:在标准输入上设置 O_NDELAY:当进程退出时,shell 退出

[英]solaris: O_NDELAY set on stdin: when process exits the shell exits

TLDR: In Solaris , if O_NDELAY is set on stdin by a child process , bash exits. TLDR:在 Solaris 中,如果子进程stdin上设置了O_NDELAY ,则bash退出。 Why?为什么?

The following code causes interactive bash (v4.3.33) or tcsh (6.19.00) shells to exit after the process finishes running:以下代码导致交互式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;
}

The versions of ksh , csh and zsh we have aren't affected by this problem.我们拥有的kshcshzsh版本不受此问题的影响。

To investigate I ran bash & csh under truss (similar to strace on Linux) like this:为了进行调查,我在truss下运行了bash & 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

After csh finishes running the process it does the following:csh完成运行该进程后,它会执行以下操作:

fcntl( 0, F_GETFL ) = FWRITE|FNDELAY
fcntl( 0, F_SETFL, FWRITE) = 0

... which gave me an idea. ......这给了我一个想法。 I changed the program to the commented out code above so it would toggle the state of O_NDELAY .我将程序更改为上面注释掉的代码,因此它会切换O_NDELAY的状态。 If I run it twice in a row bash doesn't exit.如果我连续运行两次,bash 不会退出。

This answer got me started on the right path.这个答案让我走上了正确的道路。 The man page for read (in Solaris) says:用于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

... so when bash tries to read stdin it returns 0 causing it to assume EOF was hit. ...所以当 bash 尝试读取stdin它返回 0 导致它假设 EOF 被击中。

This page indicates O_NDELAY shouldn't be used anymore, instead recommending O_NONBLOCK . 此页面表明不应再使用O_NDELAY ,而是推荐O_NONBLOCK I've found similar statements regarding O_NDELAY / FIONBIO for various flavors of UNIX.我发现了有关O_NDELAY / FIONBIO类似声明, FIONBIO于各种风格的 UNIX。

As an aside, in Linux O_NDELAY == FNDELAY == O_NONBLOCK , so it's not terribly surprising I was unable to reproduce this problem in that environment. O_NDELAY == FNDELAY == O_NONBLOCK ,在 Linux O_NDELAY == FNDELAY == O_NONBLOCK ,因此我无法在该环境中重现此问题并不奇怪。

Unfortunately, the tool that's doing this isn't one I have the source code for, though from my experimenting I've found ways to work around the problem.不幸的是,执行此操作的工具不是我拥有源代码的工具,尽管通过我的试验,我找到了解决问题的方法。

If nothing else I can make a simple program that removes O_NDELAY as above then wrap execution of this tool in a shell script that always runs the "fixer" program after the other one.如果没有别的,我可以制作一个简单的程序来删除O_NDELAY ,然后将这个工具的执行包装在一个 shell 脚本中,该脚本总是在另一个程序之后运行“修复程序”程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM