Multithreaded Programming Guide

Interrupted Waits on Condition Variables (Solaris Threads Only)

When a signal is delivered to a thread while the thread is waiting on a condition variable, the old convention (assuming that the process is not terminated) is that interrupted calls return EINTR.

The ideal new condition would be that when cond_wait(3T) and cond_timedwait(3T) return, the lock has been retaken on the mutex.

This is what is done in Solaris threads: when a thread is blocked in cond_wait() or cond_timedwait() and an unmasked, caught signal is delivered to the thread, the handler is invoked and the call to cond_wait() or cond_timedwait() returns EINTR with the mutex locked.

This implies that the mutex is locked in the signal handler because the handler might have to clean up after the thread. While this is true in the Solaris Operating Environment 2.5 release, it might change in the future, so do not rely on this behavior.


Note -

In POSIX threads, pthread_cond_wait(3T) returns from signals, but this is not an error, pthread_cond_wait() returns zero as a spurious wake-up.


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() {
    /* lock is held in the handler */
    ...
}

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 first reacquires the lock on the mutex, then calls hdlr(), 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(3T) 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. Again, the application should not rely on an interrupted cond_wait() reacquiring the mutex, because this behavior could change in the future.