pthread_cond_wait()和signal,结果取决于OS

时间:2016-08-31 06:24:10

标签: c linux multithreading macos solaris

我是多线程编程的初学者,现在我知道在等待pthead_cond_wait()时发送信号时,结果取决于操作系统。 有人能告诉我如何知道调用是如何被中断的,以及如何编写可移植代码?

#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 

使用Solaris本机cond_wait()时,它会返回EINTR,如文档所述。 有什么想法知道pthread_cond_wait()被打断了吗?

3 个答案:

答案 0 :(得分:2)

POSIX指定此函数永远不会返回EINTR。对于遗留操作系统的可移植性,无论如何都可以检查它,它不会造成伤害

更重要的是,你应该为虚假的唤醒做好准备。该函数可以在任何时候因任何原因而无法满足条件时返回零。互斥锁将被锁定。您必须检查条件,如果不满足,请返回pthread_cond_wait。

答案 1 :(得分:1)

我读了Linux pthread_cond_wait的手册,它说:

  

如果信号被传递给等待条件变量的线程,则从信号处理程序返回时,线程将继续等待条件变量,就像它没有被中断一样,或者由于虚假唤醒而返回零。

我猜其他操作系统也有手册可以帮助你搞清楚。

答案 2 :(得分:0)

非常感谢大家。 现在我知道使用信号停止长时间等待状态不起作用。 pthread_cond_wait()恢复等待条件,好像它没有被中断,或者由于虚假唤醒而返回零。 然后我想这样做,我需要第二个锁,如

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;

此致