多线程编程指南

中断对条件变量的等待

将捕获到的已取消屏蔽的信号传送到等待条件变量的线程时,线程将从虚假唤醒的信号处理程序中返回。 虚假唤醒是指不是由其他线程中的条件信号调用导致的唤醒。在这种情况下,Solaris 线程接口 cond_wait()cond_timedwait() 将返回 EINTR,而 POSIX 线程接口 pthread_cond_wait()pthread_cond_timedwait() 将返回 0。在所有情况下,从条件等待返回之前都将重新获取关联的互斥锁定。

重新获取关联的互斥锁定并不暗示线程在执行信号处理程序的同时,互斥处于锁定状态。未定义信号处理程序中的互斥状态。

由于在 Solaris 9 发行版之前的 Solaris 软件发行版中实现了 libthread,因而保证了在处于信号处理程序中时保留了互斥。依赖此原有行为的应用程序需要修改 Solaris 9 发行版以及后续发行版。

示例 5–4 将对处理程序清除加以说明。


示例 5–4 条件变量和中断的等待

int sig_catcher() {

    sigset_t set;

    void hdlr();



    mutex_lock(&mut);



    sigemptyset(&set);

    sigaddset(&set, SIGINT);

    sigsetmask(SIG_UNBLOCK, &set, 0);



    if (cond_wait(&cond, &mut) == EINTR) {

        /* signal occurred and lock is held */

        cleanup();

        mutex_unlock(&mut);

        return(0);

    }

    normal_processing();

    mutex_unlock(&mut);

    return(1);

}



void hdlr() {

    /* state of the lock is undefined */

    ...

}

假设 SIGINT 信号在进入 sig_catcher() 时在所有线程中受到阻塞。此外,还假设已通过调用 sigaction(2) 建立了 hdlr()(作为 SIGINT 信号的处理程序)。如果在线程处于 cond_wait() 中时将捕获到的已取消屏蔽的 SIGINT 信号实例传送到该线程,该线程将调用 hdlr()。然后,线程将返回到 cond_wait() 函数(如有必要,将在此处重新获取互斥锁定),并从 cond_wait() 返回 EINTR

是否已针对 sigaction()SA_RESTART 指定为标志在此处无影响。cond_wait(3C) 不是系统调用,也不会自动重新启动。如果在 cond_wait() 中阻塞线程时出现捕获的信号,则调用将始终返回 EINTR