这是我在这里发表的第一篇文章,请原谅任何格式问题。
我有一个交互式程序,它产生外部进程并监视它们的IO。事情很好,直到我用“mpiexec”产生一些东西,之后STDIN似乎打破了。
我意识到这对于大多数人来说很难重现,但是如果有人看到任何明显的或知道这个问题的话......请帮忙!
这是一个片段:
int main( ... )
{
std::string choice;
while(std::getline(std::cin,choice)){
if(!choice.empty()){
if(choice == "Parallel"){
system("mpiexec ./aprogram");
}
if(choice == "Serial"){
system("./aprogram");
}
// Now the external process is done... so far, so good
std::cout << "Program is done. Press ENTER to continue."
<< std::endl;
// This next line *works* if the external process was serial
// But *fails* when "mpiexec" was invoked
std::getline(std::cin,choice);
if(std::cin.eof()){
std::cout << "STDIN has been closed." << std::endl;
exit(1);
}
}
}
}
我尝试了各种各样的 lot ,例如管道,显式分叉,细致的描述符管理。最奇怪的是,如果我复制并保存stdin然后在“mpiexec”返回后恢复它,那么我不再在std :: cin上获得EOF,而是std :: getline(std :: cin,... )不再阻止!该程序进入无限循环,在std :: readline调用中读取std :: cin的零字节。
如果,当外部进程在mpiexec下运行时,我将一堆数据堆叠到std :: cin中(例如通过输入),然后对std :: readline的后续调用正确地解析了我所滞留的数据行在那里,但是再次......一旦完成读取数据,它就会继续进入无限循环(即,即使没有数据要读取,也不会阻塞std :: readline(std :: cin,..)呃。太烦人了。
非常感谢任何帮助。
干杯!
答案 0 :(得分:1)
我想我已经解决了你的问题,对我来说,串口或并口的调用被阻止了,我认为这是std :: cin.eof()测试,
std::getline(std::cin,choice);
if(std::cin.eof()){
td::cout << "STDIN has been closed." << std::endl;
exit(1);
}
但是,将其更改为std :: cin.get(),对于并行运行和串行运行都非常有用。
if(std::cin.get()) {
std::cout << "STDIN has been closed." << std::endl;
exit(1);
}
适用于我的系统。
答案 1 :(得分:0)
修改:错误报告已moved to GitHub。
好的,这不是一个真正的答案,但显然没有足够的声誉来评论这个问题。
我和我的同事遇到了这个问题,并对其进行了追踪。你必须跳过一大堆箍才能在mpich bug report上添加评论,但我不希望我的发现消失在以太中,所以我在这里添加它们。 (如果有人在阅读此文件时有一个mpich Trac登录,那么如果您可以将此信息添加到故障单中,那就太棒了。)
Mpich确实似乎有一个错误,它在常见模式下在O_NONBLOCK
的stdout / stderr文件描述符上设置mpirun
标志。 mpirun
退出后,这些设置会停留。但是,此错误通常不会浮出水面,因为bash
在运行的每个命令之后都有代码可以关闭其附加流的非阻塞标志。
mpirun
中直接负责的代码位于alloc_fwd_hash
中的src/pm/hydra/utils/sock.sock.c
。它由src/pm/hydra/tools/bootstrap/external/external_common_launch.c
函数中HYDT_bscd_common_launch_procs
之类的地方的代码触发,其中有一些解复用程序注册步骤涉及最终调用HYDT_bscu_stdio_cb
函数的回调alloc_fwd_hash
。还有一些其他类似的代码片段也设置了HYDT_bscu_stdio_cb
回调,并且通过我阅读代码,应该触发相同的问题。我不太了解mpich了解哪一块有问题,但我相信mpich将TTY文件描述符设置为非阻塞模式是不合适的。
您可以使用Homebrew版本的bash在OS X上运行mpirun
来触发此错误。 Homebrew的bash是版本4.4,由于我不完全清楚的原因,似乎没有激活清除O_NONBLOCK
标志的代码段。 OSX上的bash的默认版本是版本3, 清除该标志,防止错误出现。 Macports版本的Bash 4也表明了这个错误。