多线程编程指南

完成语义

另一种处理信号的方式是使用完成语义。

当信号指明发生灾难性情况,导致没有理由继续执行当前代码块时,请使用完成语义。信号处理程序将代替其余有问题的块运行。换句话说,信号处理程序将完成该块。

示例 5–3 中,所讨论的块是 if 语句的 then 部分的主体。对 setjmp(3C) 的调用会在 jbuf 中保存程序的当前寄存器状态并返回 0,从而执行块。


示例 5–3 完成语义

sigjmp_buf jbuf;

void mult_divide(void) {

    int a, b, c, d;

    void problem();



    sigset(SIGFPE, problem);

    while (1) {

        if (sigsetjmp(&jbuf) == 0) {

            printf("Three numbers, please:\n");

            scanf("%d %d %d", &a, &b, &c);

            d = a*b/c;

            printf("%d*%d/%d = %d\n", a, b, c, d);

        }

    }

}



void problem(int sig) {

    printf("Couldn't deal with them, try again\n");

    siglongjmp(&jbuf, 1);

}

如果出现 SIGFPE 浮点异常,则系统将调用信号处理程序。

信号处理程序将调用 siglongjmp(3C)(用于恢复 jbuf 中保存的寄存器状态),进而导致程序再次从 sigsetjmp() 返回。保存的寄存器包括程序计数器和栈指针。

但是,此时 sigsetjmp(3C) 将返回 siglongjmp() 的第二个参数(值为 1)。请注意,块将被跳过,而仅在下一次迭代 while 循环期间执行。

可以在多线程程序中使用 sigsetjmp(3C)siglongjmp(3C)。请注意,一个线程永远不会执行使用另一个线程的 sigsetjmp() 结果的 siglongjmp()

此外,sigsetjmp()siglongjmp() 可以恢复和保存信号掩码,而 setjmp(3C)longjmp(3C) 不会执行这些操作。

使用信号处理程序时,请使用 sigsetjmp()siglongjmp()

完成语义通常用于处理异常。需要特别指出的是,Sun AdaTM 编程语言就使用此模型。


注 –

请记住,不得sigwait(2) 与同步信号一同使用。