可以将信号处理后,C程序继续执行? [英] Can a C program continue execution after a signal is handled?

查看:190
本文介绍了可以将信号处理后,C程序继续执行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在信号通过C语言在处理新的Unix和我一直在寻找它的一些教程(纯粹出于兴趣)。

我的问题是,是否有可能继续执行程序过去,其中一个信号处理点?

据我所知,信号处理函数执行清理,但在异常处理(如C ++)的精神,是有可能的信号,以相同的方式和程序继续正常运行处理?

目前进入无限循环(presumably的方式退出将调用退出(1))。

我的意图将是 B 来分配1和程序完成正常(如果可能的话,当然)。

下面是我的code:

 的#include<&signal.h中GT;
#包括LT&;&stdio.h中GT;INT 1 = 5;
INT B = 0;无效赶上(INT SIG)
{
    的printf(夹缝信号,现在将处理它的\\ n);
    B = 1;
}INT主要(无效)
{
    信号(SIGFPE,捕捉);    INT C = A / B;    返回0;
}

此外,由于C是程序性的,怎么来的信号处理程序声明之前实际上后者执行后调用违规的声明?

最后,为了处理函数来完成其收拾妥当,都低于需要的变量在一个异常的情况下,清理需要之前,要声明的函数,对吧?

提前为你的答案和道歉,如果由于上面的一些是非常明显的。


解决方案

是的,这就是信号处理是。但有些信号需要以特殊处理,让程序继续(例如SIGSEGV,SIGFPE,...)。

见人signaction:


  

据POSIX,一个过程的行为是不确定它忽视了一个SIGFPE,SIGILL或SIGSEGV信号,这不是以后
  通过击杀(2)产生或提高(3)。整数被零除有未定义的结果。在某些架构下,会生成一个
  SIGFPE信号。 (也划分最负整数-1可能会产生SIGFPE。)忽略这个信号可能会导致
         死循环。


现在,你的的无视信号,通过不的发生(再次)做任何事情,以prevent它。您需要在信号处理函数的执行上下文并手动修复它,它涉及到覆盖一些寄存器。


  

如果在其中sa_flags指定SA_SIGINFO,那么sa_sigaction(而不是
  sa_handler)指定正负号的信号处理功能。这个
  函数接收信号编号作为第一个参数,一个指针
  到siginfo_t作为第二个参数和一个指向一个ucontext_t
  (转换为void *)作为其第三个参数。 (通常,处理程序
  功能不作任何使用第三个参数。看到
  的getContext(2)为约ucontext_t进一步的信息。)


上下文可在故障时访问寄存器和需要改变,让你的程序继续运行。看到这个 LKML帖子。由于没有提到的, siglongjmp 也可能是一种选择。该帖子还提供了处理错误,而无需进行变量的全局等相当可重复使用的解决方案:


  

因为你处理它youself,你有你想要的任何灵活性
  与错误处理。例如,可以使故障处理程序
  跳转到一些指定的点在你的函数类似
  这样的:


  __label__ error_handler;
 __asm​​ __(DIVL%2
         := A(低),= D(高)
         :G(除数),C(安培;&安培; error_handler))
 ...做正常的情况下... error_handler:
     ...对证零除或溢出,所以无论你想..


  

然后,你的SIGFPE处理程序只需要像做


  
  

context.eip = context.ecx;


I'm new at signal handling in Unix through C and I have been looking at some tutorials on it (out of pure interest).

My questions is, is it possible to continue execution of a program past the point where a signal is handled?

I understand that the signal handling function does the cleanup but in the spirit of exception handling (such as in C++), is it possible for that signal to be handled in the same fashion and for the program to continue running normally?

At the moment catch goes in an infinite loop (presumably a way to quit would be to call exit(1) ).

My intention would be for b to be assigned 1 and for the program to finish gracefully (if that is possible of course).

Here's my code:

#include <signal.h>
#include <stdio.h>

int a = 5;
int b = 0;

void catch(int sig)
{
    printf("Caught the signal, will handle it now\n");
    b = 1;
}

int main(void)
{
    signal(SIGFPE, catch);

    int c = a / b;

    return 0;
}

Also, as C is procedural, how come the signal handler declared before the offending statement is actually called after the latter has executed?

And finally, in order for the handling function to do its clean up properly, all the variables than need to be cleaned up in the event of an exception need to be declared prior to the function, right?

Thanks in advance for your answers and apologies if some of the above is very obvious.

解决方案

Yes, that's what signal handlers are for. But some signals need to be handled specially in order to allow the program to continue (e.g. SIGSEGV, SIGFPE, …).

See man signaction:

According to POSIX, the behavior of a process is undefined after it ignores a SIGFPE, SIGILL, or SIGSEGV signal that was not generated by kill(2) or raise(3). Integer division by zero has undefined result. On some architectures it will generate a SIGFPE signal. (Also dividing the most negative integer by -1 may generate SIGFPE.) Ignoring this signal might lead to an endless loop.

Right now, you are ignoring the signal, by not doing anything to prevent it from happening (again). You need the execution context in the signal handler and fix it up manually, which involves overwriting some registers.

If SA_SIGINFO is specified in sa_flags, then sa_sigaction (instead of sa_handler) specifies the signal-handling function for signum. This function receives the signal number as its first argument, a pointer to a siginfo_t as its second argument and a pointer to a ucontext_t (cast to void *) as its third argument. (Commonly, the handler function doesn't make any use of the third argument. See getcontext(2) for further information about ucontext_t.)

The context allows access to the registers at the time of fault and needs to be changed to allow your program to continue. See this lkml post. As mentioned there, siglongjmp might also be an option. The post also offers a rather reusable solution for handling the error, without having to make variables global etc.:

And because you handle it youself, you have any flexibility you want to with error handling. For example, you can make the fault handler jump to some specified point in your function with something like this:

 __label__ error_handler;   
 __asm__("divl %2"      
         :"=a" (low), "=d" (high)       
         :"g" (divisor), "c" (&&error_handler))     
 ... do normal cases ...

 error_handler:     
     ... check against zero division or overflow, so  whatever you want to ..

Then, your handler for SIGFPE needs only to do something like

context.eip = context.ecx;

这篇关于可以将信号处理后,C程序继续执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆