kaotan
kaotan

Reputation: 11

pthread_cond_wait() and signal, the result depend on OS

I am a beginner of multi-threaded programming, and now I know that when a signal was sent while waiting with pthead_cond_wait(), the result depends on the OS. Can somebody tell me how to know how the call was interrupted, and how to write portable code?

#include <stdio.h>
#include <signal.h>
#include <pthread.h>

void
sigusr1_handler(int sig)
{
    printf("signal called\n");
}

int
main()
{
    int n;
    pthread_mutex_t mut;
    pthread_cond_t cond;
    struct timespec ts;

    signal(SIGUSR1, sigusr1_handler);
    pthread_mutex_init(&mut, NULL);
    pthread_cond_init(&cond, NULL);

    pthread_mutex_lock(&mut);
    printf("before cond_wait\n");
    n = pthread_cond_wait(&cond, &mut);
    printf("after pthread_cond_wait : %d\n", n);
    perror("error pthread_cond_wait:");

    pthread_mutex_unlock(&mut);
    return 0;
}

MacOS X 10.11.4
cc -o condwait condwait.c -lpthread

Linux 2.6.32-642.3.1.el6.x86_64
gcc -o condwait condwait.c -lpthread

Solaris11 5.11 11.2
cc -D_POSIX_C_SOURCE -D_REENTRANT -mt -o condwait condwait.c -lpthread

MacOS X
$ ./condwait &
[1] xxxxx
$ kill -USR1 %1
signal called
after pthread_cond_wait : 0
error pthread_cond_wait:: Unknown error: 260

Solaris
$ ./condwait &
[1] xxxxx
$ kill -USR1 %1
signal called
after pthread_cond_wait : 0
error pthread_cond_wait : Error 0

Linux
$ ./condwait &
[1] xxxxx
$ kill -USR1 %1
signal called
$ jobs
[1]+  Running 

When using Solaris native cond_wait(), it returns EINTR as documented. Is there any idea how to know that pthread_cond_wait() was interrupted?

Upvotes: 1

Views: 1906

Answers (3)

kaotan
kaotan

Reputation: 11

Thank you very much for everyone. Now I know that with using signal to stop long waiting condition do not work. pthread_cond_wait() resume waiting for the condition as if it was not interrupted, or it returns zero due to spurious wakeup. Then I want to do that, I will need a second lock like

pthread_mutex_lock(&mut);
while(condition_is_false) {
  n = pthread_cond_timedwait();
  if (n == ETIMEDOUT) {
    pthread_mutex_lock(&mut2);
    if (condition2_is_true) {
      pthread_mutex_unlock(&mut2);
      pthread_mutex_unlock(&mut);
      return STOPPED;
    }
    pthread_mutex_unlock(&mut2);
  }
}
pthread_mutex_unlock(&mut);
return 0;

Regards,

Upvotes: 0

jacob
jacob

Reputation: 681

I read the Linux pthread_cond_wait's man manual, it says:

If a signal is delivered to a thread waiting for a condition variable, upon return from the signal handler the thread resumes waiting for the condition variable as if it was not interrupted, or it shall return zero due to spurious wakeup.

I guess other OS's also have manuals to help you figure it out.

Upvotes: 1

n. m. could be an AI
n. m. could be an AI

Reputation: 119847

POSIX specifies that this function will never return EINTR. For portability to legacy OSes you can check for it anyway, it doesn't hurt

More importantly, you should be prepared for spurious wakeups. The function can return zero at any time for any reason wiith the condition not being met. The mutex will be locked. You have to check the condition and, if not met, go back to pthread_cond_wait.

Upvotes: 3

Related Questions