我想运行我的代码的一部分,但可以选择在它完全完成之前中断它(ctrl-c)并继续执行我的其余代码。 (我正在Linux平台上工作。)
我的猜测是创建fork,调用方法,然后使用信号处理。信号处理需要哪些步骤?
void Manager::Run()
{
pid_t pID = fork();
if( pID<0 )
exit(1);//give up here
else if( pID==0 ) {
BuildList(); //I'd like the option to ctrl-c this only
//some code here catch user signal interrupt?
}
else {;}
waitpid(pID,NULL,0);//pause until BuildList() is done or interrupted
PrintList();
}
看起来我想在if / else部分的某个地方使用像signal(SIGINT,sigint)这样的行。我需要定义一个这样的函数:
sigint(int param){ signal(param, SIG_DFL);};
除了我只想杀死子进程。
这是解决我问题的正确方法吗?如果是这样,需要什么信号处理才能使其工作?
更新
为了更完整地解决我的问题,我探索了建议的非分叉方法。没有分叉我应该能做到这一点似乎是合理的。不幸的是,我现在因为我的一些尝试而陷入编译错误。我已经包含了更新的代码和新的错误。
static void sighandler(int signum)
{
PrintList();
exit(1);
};
Manager.cc包含
void Manager::Run()
{
signal(SIGINT,sighandler);//sets up sighandler()
BuildList(); //add elements to a list
signal(SIGINT,SIG_DFL); //restore default
PrintList();
}
如果sighandler功能不是静态的,我得到这个:
error: argument of type 'void (Manager::)(int)' does not match 'void (*)(int)'
在Manager :: Run()的调用signal(SIGINT,sighandler)
上设置处理程序。
如果我在静态sighandler函数中调用PrintList(),我得到这个:
error: cannot call member function 'void Manager::PrintList()' without object
在sighandler()的PrintList();
调用中。
最后我注意到使PrintList()成为静态函数(使用静态sighandler),我在List和迭代器上得到这些错误以逐步浏览列表。
error: invalid use of member 'Manager::theList' in static member function
error: invalid use of member 'Manager::it' in static member function
解决这些错误的任何聪明方法?
答案 0 :(得分:2)
根据您希望中断的功能,可以在不分叉的情况下实现。
如果函数在循环中进行处理,则信号处理程序可以设置一个布尔值,表示您希望处理停止。循环可以只检查这个布尔值,一旦信号处理程序设置,函数就可以安全地退出并保持一致状态。
答案 1 :(得分:2)
除非你明确地分享记忆(比如说mmap
),否则你的fork
孩子不会产生你能看到的结果。假设您已修复此问题,您可以signal(SIGINT, SIG_IGN)
忽略父级中的ctrl-C(fork
之前),然后将其重置为signal(SIGINT, SIG_DFL)
的子级中的默认值。
如果你改用线程(简化内存共享),那么答案就会改变:SIGINT
是一个异步信号,这意味着它不是由于执行一条指令而产生的。特定线程(相反,SIGSEGV
是同步信号)。在线程应用程序中,所有线程都有一个共享信号处理程序。对于异步信号,它可以传递给任何线程。该处理程序需要将一些变量设置为BuildList()
的内部循环,以便它可以正常终止。
关于忽略SIGINT
的注意事项: 我不可避免地发现自己在诅咒这些应用程序,因为我找到了其他方法来杀死它们(ctrl- \发送SIGQUIT
或ctrl-Z + kill
)。