Chinaunix首页 | 论坛 | 博客
  • 博客访问: 993297
  • 博文数量: 200
  • 博客积分: 5011
  • 博客等级: 大校
  • 技术积分: 2479
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-27 15:07
文章分类

全部博文(200)

文章存档

2009年(12)

2008年(190)

我的朋友

分类:

2008-12-08 12:17:15

10.17 abort function

ISO C说,abort函数会调用raise()来对本进程发送一个SIGABRT信号。

我们可以捕捉该信号,来做一些操作,然后退出。

不同的实现,有不同的abort函数,例如,有的实现中,abort函数发送的是SIGILL信号,会导致进程terminate并且coredump,从而abort函数不会返回。有的实现中,abort函数会发送SIGIOT信号,并且abort函数会返回。

不同的abort实现,对standard i/o stream的处理也不一样,有的实现会flush标准输出流,有的不会。一个比较好的作法是在我们调用abort函数之前,自己去flush

如下有一个posix.1 abort函数的实现,它可以保证,不管你的外界调用者对SIGABRT信号是如何设置的,一般情况下,都会将standard i/o streams flush掉。当然有个例外(下面会讲述):

Figure 10.25. Implementation of POSIX.1 abort

#include

#include

#include

#include

 

void

abort(void)         /* POSIX-style abort() function */

{

    sigset_t           mask;

    struct sigaction   action;

 

    /*

     * Caller can't ignore SIGABRT, if so reset to default.

     */

    sigaction(SIGABRT, NULL, &action);

    if (action.sa_handler == SIG_IGN) {

        action.sa_handler = SIG_DFL;

        sigaction(SIGABRT, &action, NULL);

    }

    if (action.sa_handler == SIG_DFL)

        fflush(NULL);           /* flush all open stdio streams */

 

    /*

     * Caller can't block SIGABRT; make sure it's unblocked.

     */

    sigfillset(&mask);

    sigdelset(&mask, SIGABRT);  /* mask has only SIGABRT turned off */

    sigprocmask(SIG_SETMASK, &mask, NULL);

    kill(getpid(), SIGABRT);    /* send the signal */

 

    /*

     * If we're here, process caught SIGABRT and returned.

     */

    fflush(NULL);               /* flush all open stdio streams */

    action.sa_handler = SIG_DFL;

    sigaction(SIGABRT, &action, NULL);  /* reset to default */

    sigprocmask(SIG_SETMASK, &mask, NULL);  /* just in case ... */

    kill(getpid(), SIGABRT);                /* and one more time */

    exit(1);    /* this should never be executed ... */

}

1.如果外界对SIGABRTSIG_IGN,那么在abort函数里,将其改成了SIG_DFL

2.然后调用了fflush,这说明如果外界对SIGABRTSIG_IGN或者SIG_DFLabort函数就会给我们调用fflush.

3. 接下来,我们block所有的信号,除了SIGABRT,然后发送SIGABRT给自己。

4.我们知道如果kill发信号给自己,且信号没有被block,那么handler会再kill返回之前调用。

5.如果此时SIGABRT的处理是SIG_DFL,那么进程就结束了,kill 不会返回,如果SIGABRT被我们catch, 那么handler会被调用,且如果handler没有调用exit()之类的函数,那么handler结束后,kill返回,如果handler调用了exit(),那么exit()会将stream flush,然后关闭,退出。如果handler调用了_exit()那么stream就不会被flush,也不会被关闭,退出的时候file descriptor会被关闭,此时stream的数据丢掉了。

6.如果kill返回了,说明handler执行完了并且也没有调用exit类函数。好,我们将SIGABRT的处理设置为SIG_DFL,然后发该信号,就会被终止了。

阅读(952) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~