sigset:忽略Unix中的ctrl-c

Jar*_*ary 3 c unix

我试图让我的程序忽略Ctrl+ C在unix中似乎工作,问题是它继续写"语法错误".这是代码

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;
}
Run Code Online (Sandbox Code Playgroud)

每次我点击Ctrl+ C它再次运行getUserInput,这是预期的行为,但它也写了"语法错误".我检查并执行"忽略"函数,一旦执行完毕,它就会输出错误信息,我不知道为什么.

有人有任何线索吗?

非常感谢你,

Jary

Jon*_*ler 8

不要用sigset().虽然它在POSIX 2008中,但它已被标记为过时 - 并且在线程程序中也是不安全的.

然后signal(),您可以选择,它受到ISO C的保护,但具有一些不良特性,sigaction()这是POSIX系统中的首选解决方案.

信号处理的一个关键点是确保您不会捕获进入程序时忽略的任何信号 - 除非您知道调用者无法识别的内容(例如您需要为死亡的孩子捕获SIGCHLD信号).

这导致了自远古以来传播的标准配方signal():

if (signal(SIGINT, SIG_IGN) != SIG_IGN)
    signal(SIGINT, ignore);
Run Code Online (Sandbox Code Playgroud)

或者,对于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);
}
Run Code Online (Sandbox Code Playgroud)

由于您没有向我们展示该getUserInput()功能,因此我们无法预测您为什么会看到"语法错误".但是,如果你有一个语法在工作,很可能你的读取没有返回有效数据,并且解析器不满意缓冲区中剩余的内容以便它处理.


Mat*_*ery 5

(注意:为了更具可移植性,您应该使用signal()(C标准库)或sigaction()(POSIX)代替sigset(),但我认为这不是问题.)

你并没有真正忽视这里的信号; 你正在抓住它并采取自己的行动 - 但是由于中断,系统调用可能会返回错误.

例如,您可能导致read系统调用失败EINTR.我怀疑真正的问题是内部的一些代码getUserInput()没有处理这个错误情况.

您可以通过处理程序设置为特殊值完全忽略信号SIG_IGN,这应该与任何的工作sigset(),signal()sigaction().