方案1:
#include<stdio.h>
#include<signal.h>
void handler(int sig);
void main()
{
printf("PID: %d\n",getpid());
signal(SIGABRT,handler);
while(1){
printf("Hai\n");
sleep(1);
abort();
}
}
void handler(int sig)
{
printf("Signal handled\n");
}输出1:
$ ./a.out
PID: 32235
Hai
Signal handled
Aborted (core dumped)
$根据引用,abort函数的工作方式与raise(SIGABRT)类似。因此,abort()函数生成的信号是SIGABRT。因此,我创建了上面的程序。
在该程序中,SIGABRT信号被处理。在信号处理程序执行之后,它不会返回到调用它的main函数。为什么在处理程序完成后,它没有返回到main函数?
方案2:
#include<stdio.h>
#include<signal.h>
void handler(int sig);
void main()
{
printf("PID: %d\n",getpid());
signal(SIGABRT,handler);
while(1){
printf("Hai\n");
sleep(1);
}
}
void handler(int sig)
{
printf("Signal handled\n");
}输出2:
$ ./a.out
PID: 32247
Hai
Hai
Hai
Signal handled
Hai
Signal handled
Hai
Hai
^C
$ 与程序1不同,程序2按预期执行。在上面的程序中,信号通过命令行通过kill命令发送到进程,如下所示。
$ kill -6 32247
$ kill -6 32247因此,一旦信号发生,处理程序函数就会执行,然后返回到主函数。但是它不会在程序1中发生,为什么它会这样呢?abort函数和SIGABRT是不同的?
发布于 2015-11-06 19:59:19
请参阅来自man 3 abort的这篇文档
这会导致进程异常终止,除非SIGABRT信号被捕获为,并且信号处理程序不返回(参见
longjmp(3))。
还有这个:
如果
SIGABRT信号被忽略或被返回的处理程序捕获,abort()函数仍将终止进程。它通过恢复SIGABRT的默认配置,然后第二次提高信号来实现这一点。
因此,防止abort()中止程序的唯一方法是从信号处理程序执行longjmp()-ing。
发布于 2015-11-06 20:01:12
Libc实现了abort()。在它们的实现中,abort()检查进程是否仍在运行,因为abort()是在raise(SIGABRT)之后执行的。如果是,那么它就知道用户已经处理了SIGABRT。根据文档,这并不重要,因为进程仍然会退出:
您可以在GLIBC源代码(stdlib/abort.c)中看到确切的实现:
/* Cause an abnormal program termination with core-dump. */
void
abort (void)
{
struct sigaction act;
sigset_t sigs;
/* First acquire the lock. */
__libc_lock_lock_recursive (lock);
/* Now it's for sure we are alone. But recursive calls are possible. */
/* Unlock SIGABRT. */
if (stage == 0)
{
++stage;
if (__sigemptyset (&sigs) == 0 &&
__sigaddset (&sigs, SIGABRT) == 0)
__sigprocmask (SIG_UNBLOCK, &sigs, (sigset_t *) NULL);
}
/* Flush all streams. We cannot close them now because the user
might have registered a handler for SIGABRT. */
if (stage == 1)
{
++stage;
fflush (NULL);
}
/* Send signal which possibly calls a user handler. */
if (stage == 2)
{
/* This stage is special: we must allow repeated calls of
`abort' when a user defined handler for SIGABRT is installed.
This is risky since the `raise' implementation might also
fail but I don't see another possibility. */
int save_stage = stage;
stage = 0;
__libc_lock_unlock_recursive (lock);
raise (SIGABRT);
__libc_lock_lock_recursive (lock);
stage = save_stage + 1;
}
/* There was a handler installed. Now remove it. */
if (stage == 3)
{
++stage;
memset (&act, '\0', sizeof (struct sigaction));
act.sa_handler = SIG_DFL;
__sigfillset (&act.sa_mask);
act.sa_flags = 0;
__sigaction (SIGABRT, &act, NULL);
}
/* Now close the streams which also flushes the output the user
defined handler might has produced. */
if (stage == 4)
{
++stage;
__fcloseall ();
}
/* Try again. */
if (stage == 5)
{
++stage;
raise (SIGABRT);
}
/* Now try to abort using the system specific command. */
if (stage == 6)
{
++stage;
ABORT_INSTRUCTION;
}
/* If we can't signal ourselves and the abort instruction failed, exit. */
if (stage == 7)
{
++stage;
_exit (127);
}
/* If even this fails try to use the provided instruction to crash
or otherwise make sure we never return. */
while (1)
/* Try for ever and ever. */
ABORT_INSTRUCTION;
}发布于 2015-11-06 19:59:11
abort函数发送的SIGABRT信号是真的,但是无论您是否捕获(或忽略)该信号,abort函数仍将退出您的进程。
在链接的手册页面中:
返回值
abort()函数从不返回。
https://stackoverflow.com/questions/33566228
复制相似问题