在Linux上,在CTRL+C中断时退出应用程序的最佳方法。(C/C++)
我的应用程序在其主线程中检查用户输入:在Linux上,在CTRL+C中断时退出应用程序的最佳方法。(C/C++),c++,c,linux,C++,C,Linux,我的应用程序在其主线程中检查用户输入: while (running) { std::string console; if (std::getline(std::cin, console)) { process(&console); } } 在此之前,我已经设置了一个sigaction来检测CTRL+C,并结合一个函数处理程序来关闭其他线程。 现在,当SIGINT发生时,应用程序崩溃;GDB输出: 我环顾四周,发现了其他解决方案,比如非
while (running)
{
std::string console;
if (std::getline(std::cin, console))
{
process(&console);
}
}
在此之前,我已经设置了一个sigaction来检测CTRL+C,并结合一个函数处理程序来关闭其他线程。
现在,当SIGINT发生时,应用程序崩溃;GDB输出:
我环顾四周,发现了其他解决方案,比如非阻塞输入读取:伪代码
while (running)
{
if (input_avail())
{
getinput
process
}
else
sleep(1);
}
但即使这样,我在睡眠功能nanosleep中也失败了:
所以我很好奇其他人是如何做到这一点的
使用g++v4.8.2内核3.10
要求提供的其他信息:
在主线程循环之前:
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = signalinfo;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGTERM, &sigIntHandler, NULL);
sigaction(SIGQUIT, &sigIntHandler, NULL);
sigaction(SIGINT, &sigIntHandler, NULL);
信号处理器:
void signalinfo(int signum)
{
// Only setting a flag so threads know to exit.
pCore->Termination(signum);
}
不确定它是否回答了您的问题,但XBoard协议的文档说明了引擎如何处理从stdin读取的一些常见策略 它基本上描述了如何实现非阻塞伪代码 资料来源: 。。。在输入端,您可能希望在搜索过程中进行轮询,并在收到新输入时停止它。如果您实现了思考,您将需要这样做,以便在用户移动时停止思考。你也应该在正常思考的过程中进行投票,这样你就可以实现?“立即移动”命令,这样,如果xboard想要结束游戏或终止引擎,您可以立即响应结果、强制或退出命令。缓冲输入使轮询更加复杂-轮询时,如果缓冲区中有字符或基础文件描述符中有可用字符,则必须停止搜索 解决此问题的最直接方法是使用无缓冲操作系统调用直接读取和轮询底层文件描述符。在Unix上,使用read0。。。从标准输入中读取,并使用“选择”对其进行轮询。请参阅手册页read2并选择2。不要遵循GNU国际象棋4的示例,而是使用FIONREAD ioctl轮询输入。它不是很便携;也就是说,它并不存在于所有版本的Unix上,并且在某些有它的版本上被破坏。在Win32上,您可以使用Unix,如_read0。。。或要读取的本机Win32 ReadFile。不幸的是,在Win32下,根据输入设备是管道、控制台还是其他设备,用于轮询的函数是不同的。更多微软的大脑损伤-他们从来没有听说过设备独立性吗?对于管道,即使管道未命名,也可以使用PeekNamedPipe进行轮询。对于控制台,可以使用GetNumberOfConsoleInputEvents。仅对于套接字,可以使用select。也许可以更广泛地使用WaitForSingleObject,但我还没有尝试过。在Crafty的utility.c中可以找到一些实现这些功能的代码,但我不能保证这些代码都是正确的或最优的 解决此问题的第二种方法可能是要求I/O库不要缓冲输入。然后,如上所述轮询底层文件描述符应该是安全的。使用C,您可以尝试调用setbufstdin,NULL。然而,我从未尝试过这个。另外,如果您使用scanf,至少在某些模式下,可能会出现问题,因为scanf有时需要读取一个额外的字符并将其推回缓冲区;因此,即使您要求取消缓冲stdio,也有一个单字符的后推缓冲区。用C++,你可以尝试CIN。RDBUF- > StBufNULL,0,但是,我从来没有尝试过。 解决此问题的第三种方法是在轮询时检查缓冲区中是否有字符。C I/O库通常不提供任何可移植的方法来实现这一点。在C++下,可以使用CIN。据报道,该方法适用于EXCESS。请记住,如果缓冲区中没有字符,您也必须使用上述方法轮询底层文件描述符 解决此问题的第四种方法是使用单独的线程从stdin读取。如果您熟悉线程编程,那么这种方法非常有效。当引擎的主线程进行思考时,该线程可能会一直被阻塞,等待输入。当输入到达时,您让线程将输入放入缓冲区,并在全局变量中设置一个标志。然后,您的搜索例程定期测试全局变量以查看是否有要处理的输入,如果有,则停止。ICC timestamp和FICS timeseal的WinBoard和my Win32端口使用线程处理多个输入源
你能告诉我们你是如何处理这个信号的吗?在多线程程序中正确处理UNIX信号绝非易事。在此之前,我已经设置了一个sigaction来检测CTRL+CI,但在您的代码示例中无法发现这一点。请像往常一样提供一个服务!我完全不明白为什么这个问题被否决了?语言标记不清楚,代码示例不完整,调试工作不足,…cin不提供可中断io。编写自己的流后端,使用posix select和stdin文件句柄提供可中断io?您在gdb中。gdb将停止exec
默认情况下,在该信号上打印堆栈跟踪。当你在gdb之外运行时,你的应用程序是否也会崩溃?@Mellnik在收到信号后从gdb继续运行,继续运行,直到出现分段错误,并对此进行调查。或者,将系统设置为在分段错误ulimit-c unlimited之后保存崩溃转储,在没有gdb的情况下运行,然后在gdb中加载转储。INT信号不是问题所在。