&引用;杀戮-15“;触发sigaction代码,但不终止我的C程序
我有一个用C开发的程序。我在这个程序中添加了一个sigaction处理程序,以便在退出程序之前执行一些C代码:&引用;杀戮-15“;触发sigaction代码,但不终止我的C程序,c,linux,signals,kill,C,Linux,Signals,Kill,我有一个用C开发的程序。我在这个程序中添加了一个sigaction处理程序,以便在退出程序之前执行一些C代码: void signal_term_handler(int sig) { printf("EXIT :TERM signal Received!\n"); int rc = flock(pid_file, LOCK_UN | LOCK_NB); if(rc) { char *piderr = "PID file unlock failed!";
void signal_term_handler(int sig)
{
printf("EXIT :TERM signal Received!\n");
int rc = flock(pid_file, LOCK_UN | LOCK_NB);
if(rc) {
char *piderr = "PID file unlock failed!";
fprintf(stderr, "%s\n", piderr);
printf(piderr);
}
exit(EXIT_SUCCESS);
}
int main(int argc, char **argv)
{
struct sigaction sigint_action;
sigint_action.sa_handler = &signal_term_handler;
sigemptyset(&sigint_action.sa_mask);
sigint_action.sa_flags = SA_RESETHAND;
sigaction(SIGTERM, &sigint_action, NULL);
...........
}
注意:我的程序包含2个子线程正在运行
当我执行我的程序,然后我调用kill-15
来终止我的程序。我收到打印在标准输出中的消息“退出:接收到术语信号!\n”,但程序未退出
我的sigaction代码中是否遗漏了一些内容?这很可能是因为不允许您在信号处理程序中执行很多操作(调用库函数当然很粗略) 处理此类事件的正常方法是,信号处理程序设置一个变量或将正常主循环将处理的事件排队,然后退出。
exit()
不一定是异步信号安全的
要直接从信号处理程序结束进程,请调用\u exit()
或abort()
flock()
和printf
函数系列的所有成员也不是异步信号保存
有关异步信号安全函数的完整列表,请参见。我仍然怀疑您存在XY问题,即在接收到
SIGTERM
时尝试取消文件flock()
为了实现这一点(并绕过仅能在信号接收时使用异步信号安全功能的限制),请使用以下方法:
- 屏蔽主线程中应用程序要处理的所有信号
- 创建一个线程
- 通过修改线程的信号掩码,使该线程接收所有要处理的信号
- 在这个线程中,循环使用
sigwaitinfo()
来接收和发送信号
- 然后,根据该线程接收到的信号,在不受任何限制的情况下执行需要执行的操作,因为任何函数都缺少异步信号安全性
比这更糟糕的是,flock
是一个系统调用。exit
如果例程注册到atexit
,也会有问题。异步信号保存是否有flock()
的替代方法?如果没有,是否有可能实现异步信号保存?@MOHAMED:不,我没有找到一种方法来实现flock()
async signal save,除了黑客攻击glibc
和/或操作系统的内核之外。但是,从您在SIGTERM
上触发的事实来看,如果您觉得您可能有XY问题:要在程序终止时执行任何操作,请使用atexit()安装退出处理程序
将是合适的方法。下面的答案使用atexit()
作为解决方案。我不确定提议的解决方案是否是一种保存的方法。你能确认它是否是一种保存的方法吗?@mohamed:你链接的方法不会给你带来任何好处。@mohamed:只是想澄清一下:你的基地是否打算在进程“结束”时执行某些操作?如果你删除了信号处理程序中所有非法的代码,你将被解雇eft withif(rc){char*piderr=“…”;}
谢谢您的回答(+1)。这是一个有趣的解决方案,但我只想在退出之前解锁一个文件,仅此而已。所以添加这样的行为与我所做的相比看起来很复杂want@MOHAMED:尽管看起来有点复杂,但这是以灵活且最后也是最安全的方式处理信号响应的唯一方法,尤其是在处理关机情况时。Al因此,在多线程环境中处理handel信号是一种非常通用的方法。@MOHAMED:注意,当进程退出时,锁会自动释放;死进程不持有锁。