Unix pthread_cond_timedwait()不在FreeBSD上工作,返回EPERM

Unix pthread_cond_timedwait()不在FreeBSD上工作,返回EPERM,unix,pthreads,freebsd,Unix,Pthreads,Freebsd,我有一个示例程序,它创建一个pthread,等待线程加入。线程将调用phread_cond_timedwait()等待2秒。在Linux平台上,示例代码运行良好。在FreeBSD上,调用会立即返回EPERM错误代码 pthread_condition_timedwait.cpp \define\u BSD\u源 #包括 #包括 #包括 #包括 #包括 #包括 void*线程处理器(void*ptr){ pthread_cond_t cond=pthread_cond_初始值设定项; pthrea

我有一个示例程序,它创建一个pthread,等待线程加入。线程将调用phread_cond_timedwait()等待2秒。在Linux平台上,示例代码运行良好。在FreeBSD上,调用会立即返回EPERM错误代码

pthread_condition_timedwait.cpp
\define\u BSD\u源
#包括
#包括
#包括
#包括
#包括
#包括
void*线程处理器(void*ptr){
pthread_cond_t cond=pthread_cond_初始值设定项;
pthread\u mutex\u t mutex=pthread\u mutex\u初始值设定项;
结构timespects;
结构timeval-tp;
gettimeofday(&tp,NULL);
ts.tv_sec=tp.tv_sec;
ts.tv\u nsec=tp.tv\u usec*1000;
ts.tv_sec+=2;
//调用pthread_cond_timedwait()等待2秒
int rcode=pthread\u cond\u timedwait(&cond,&mutex,&ts);
if(rcode==ETIMEDOUT)
printf(“由于超时而终止\n”);
else if(rcode==EPERM)
printf(“因EPERM终止”);
其他的
printf(“返回代码为%d\n”,rcode);
返回NULL;
}
int main(int argc,字符**argv){
pthread\u t线程;
//开线
pthread_create(&thread,NULL,&thread_handler,NULL);
//等待线程完成
pthread_join(线程,NULL);
返回0;
}

如果调用timedwait的线程不拥有互斥锁,则返回EPERM。在调用timedwait之前,必须锁定互斥锁。另外,将mutex和condvar的静态初始化移动到文件范围

更新:如果您将互斥体初始化为一个错误检查互斥体,Linux也将以EPERM终止(因为在不持有互斥体的情况下调用pthread_cond_wait/timedwait是很困难的)

修改代码如下:

//#define _BSD_SOURCE                                                                                                                                                                                                                                                                     

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex;


void *thread_handler(void *ptr){

    struct timespec ts;
    struct timeval tp;

    gettimeofday(&tp, NULL);

    ts.tv_sec  = tp.tv_sec;
    ts.tv_nsec = tp.tv_usec*1000;
    ts.tv_sec += 2;

    //Invoke pthread_cond_timedwait() to wait for 2 seconds                                                                                                                                                                                                                               
    int rcode = pthread_cond_timedwait(&cond, &mutex, &ts);

    if (rcode == ETIMEDOUT)
        printf("Terminated due to time out\n");
    else if (rcode == EPERM)
        printf("Terminated due to EPERM\n");
    else
        printf("Return code is %d\n", rcode);

    return NULL;
}

int main(int argc, char** argv){

    pthread_mutexattr_t mta;
    pthread_mutexattr_init(&mta);
    pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK);

    pthread_mutex_init(&mutex, &mta);

    pthread_t thread;

    // start the thread                                                                                                                                                                                                                                                                   
    pthread_create(&thread, NULL, &thread_handler, NULL);

    // wait for thread to finish                                                                                                                                                                                                                                                          
    pthread_join(thread, NULL);
    return 0;
}
定义源代码 #包括 #包括 #包括 #包括 #包括 #包括 pthread_cond_t cond=pthread_cond_初始值设定项; pthread_mutex_t mutex; void*线程处理器(void*ptr){ 结构timespects; 结构timeval-tp; gettimeofday(&tp,NULL); ts.tv_sec=tp.tv_sec; ts.tv\u nsec=tp.tv\u usec*1000; ts.tv_sec+=2; //调用pthread_cond_timedwait()等待2秒 int rcode=pthread\u cond\u timedwait(&cond,&mutex,&ts); if(rcode==ETIMEDOUT) printf(“由于超时而终止\n”); else if(rcode==EPERM) printf(“因EPERM终止”); 其他的 printf(“返回代码为%d\n”,rcode); 返回NULL; } int main(int argc,字符**argv){ pthread_mutexttr_mta; pthread_mutexattr_init(&mta); pthread_mutextatr_settype(&mta,pthread_MUTEX_ERRORCHECK); pthread_mutex_init(&mutex,&mta); pthread\u t线程; //开线 pthread_create(&thread,NULL,&thread_handler,NULL); //等待线程完成 pthread_join(线程,NULL); 返回0; }
在内核SMP Debian 4.9.82-1+deb9u3(2018-03-02)x86_64 GNU/Linux,发行版Debian GNU/Linux buster/sid上测试。

@Yaswanth不要先尝试锁定互斥锁。@Erik Alapä谢谢。它起作用了!使用锁定的互斥锁工作。不知道为什么它会在Linux上传递。是的,调用cond_wait/timedwait而不锁定互斥锁是很奇怪的,而且也是UB。从手册页:pthread_cond_wait()和pthread_cond_timedwait()函数用于阻塞条件变量。它们被调用线程锁定的互斥锁调用,否则将导致未定义的行为。如果您打开错误检查互斥锁,Linux可能会发出错误信号。
//#define _BSD_SOURCE                                                                                                                                                                                                                                                                     

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex;


void *thread_handler(void *ptr){

    struct timespec ts;
    struct timeval tp;

    gettimeofday(&tp, NULL);

    ts.tv_sec  = tp.tv_sec;
    ts.tv_nsec = tp.tv_usec*1000;
    ts.tv_sec += 2;

    //Invoke pthread_cond_timedwait() to wait for 2 seconds                                                                                                                                                                                                                               
    int rcode = pthread_cond_timedwait(&cond, &mutex, &ts);

    if (rcode == ETIMEDOUT)
        printf("Terminated due to time out\n");
    else if (rcode == EPERM)
        printf("Terminated due to EPERM\n");
    else
        printf("Return code is %d\n", rcode);

    return NULL;
}

int main(int argc, char** argv){

    pthread_mutexattr_t mta;
    pthread_mutexattr_init(&mta);
    pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK);

    pthread_mutex_init(&mutex, &mta);

    pthread_t thread;

    // start the thread                                                                                                                                                                                                                                                                   
    pthread_create(&thread, NULL, &thread_handler, NULL);

    // wait for thread to finish                                                                                                                                                                                                                                                          
    pthread_join(thread, NULL);
    return 0;
}