我试图让我的程序在unix中忽略 Ctrl + C 似乎有效,问题是它一直在写“语法错误”。这是代码
extern "C" void ignore( int sig )
{
fprintf( stderr, "\n"); // Print a new line
// This function does nothing except ignore ctrl-c
}
int main()
{
// For ctrl-c
sigset( SIGINT, ignore );
while (1) {
getUserInput();
}
return 0;
}
每次我点击 Ctrl + C 它再次运行getUserInput,这是预期的行为,但它也写了“语法错误”。我检查了“忽略”函数并执行了,一旦执行完毕,它就会输出错误信息,我不知道为什么。
有人有任何线索吗?
非常感谢,
Jary
答案 0 :(得分:8)
请勿使用sigset()
。虽然它在POSIX 2008中,但它已被标记为过时 - 并且在线程程序中也是不安全的。
然后,您可以选择signal()
,它具有ISO C但有一些不良特性,而sigaction()
是POSIX系统中的首选解决方案。
信号处理的一个关键点是确保您不会捕获任何在您输入程序时被忽略的信号 - 除非您知道调用者无法识别的内容(例如您需要为死去的孩子捕获SIGCHLD信号)
这导致了自远古以来传承的标准配方signal()
:
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
signal(SIGINT, ignore);
或者,对于sigaction()
:
struct sigaction new_sa;
struct sigaction old_sa;
sigfillset(&new_sa.sa_mask);
new_sa.sa_handler = SIG_IGN;
new_sa.sa_flags = 0;
if (sigaction(SIGINT, &new_sa, &old_sa) == 0 && old_sa.sa_handler != SIG_IGN)
{
new_sa.sa_handler = ignore;
sigaction(SIGINT, &new_sa, 0);
}
由于您没有向我们展示getUserInput()
函数,因此我们无法预测您为什么会看到'语法错误'。但是,如果你有一个语法在起作用,那么你的读取可能不会返回有效数据,并且解析器对缓冲区中剩余的内容不满意,以便它进行处理。
答案 1 :(得分:5)
(注意:为了更具可移植性,您应该使用signal()
(C标准库)或sigaction()
(POSIX)而不是sigset()
,但我不认为这是问题此处。)
你真的没有忽略这里的信号;你正在抓住它并采取自己的行动 - 但系统调用很可能因中断而返回错误。
e.g。也许你已经导致read
系统调用失败了EINTR
。我怀疑真正的问题是getUserInput()
内的一些代码没有处理这个错误情况。
您可以通过将处理程序设置为特殊值SIG_IGN
来完全忽略该信号,该值应与sigset()
,signal()
或sigaction()
中的任何一个一起使用。
答案 2 :(得分:1)
“语法错误”消息必须来自getUserInput
函数(当然还有它调用的东西) - 您可以通过让该函数打印出它接收的内容以及它为什么抱怨来进行调查。
请注意,忽略信号的规范方法是使用预定义的SIG_IGN
作为信号处理程序。例如
sigset(SIGINT, SIG_IGN)
答案 3 :(得分:1)
ignore()
做的不仅仅是什么。
在UNIX上运行此代码时,SIGINT
将在执行getUserInput()
的同一线程上异步传递。如果在SIGINT
访问getUserInput()
时stderr
到达,则行为未定义,因为fprintf()
通常不是可重入的。 (但是,行为可能包括乱码和/或重复输出。在SIGINT
发布之前,您的程序是否打印了“语法错误”?)CERT和GNU libc有更多信息关于这个。
如果您在Win32上运行此代码,SIGINT
将以异步方式in a separate thread发送。