Multithreaded Programming Guide

Interrupted Waits on Condition Variables

When an unmasked, caught signal is delivered to a thread while the thread is waiting on a condition variable, then when the signal handler returns, the thread returns from the condition wait with a spurious wakeup (one not caused by a condition signal call from another thread). In this case, the Solaris threads interfaces (cond_wait() and cond_timedwait()) return EINTR while the POSIX threads interfaces (pthread_cond_wait() and pthread_cond_timedwait()) return 0. In all cases, the associated mutex lock is reacquired before returning from the condition wait.

This does not imply that the mutex is locked while the thread is executing the signal handler. The state of the mutex in the signal handler is undefined.

The implementation of libthread in releases of Solaris prior to the Solaris 9 release guaranteed that the mutex was held while in the signal handler. Applications that rely on this old behavior will require revision for Solaris 9 and subsequent releases.

Handler cleanup is illustrated by Example 5–4.


Example 5–4 Condition Variables and Interrupted Waits

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 */
    ...
}

Assume that the SIGINT signal is blocked in all threads on entry to sig_catcher() and that hdlr() has been established (with a call to sigaction(2)) as the handler for the SIGINT signal. When an unmasked and caught instance of the SIGINT signal is delivered to the thread while it is in cond_wait(), the thread calls hdlr(), then returns to the cond_wait() function where the lock on the mutex is reacquired, if necessary, and then returns EINTR from cond_wait().

Note that whether SA_RESTART has been specified as a flag to sigaction() has no effect here; cond_wait(3THR) is not a system call and is not automatically restarted. When a caught signal occurs while a thread is blocked in cond_wait(), the call always returns EINTR.