pthread_cond_timedwait() 不适用于 FreeBSD,returns EPERM
pthread_cond_timedwait() not working on FreeBSD, returns EPERM
我有一个创建 pthread 的示例程序,等待线程加入。线程将调用 phread_cond_timedwait() 等待 2 秒。在 Linux 平台上,示例代码运行良好。在 FreeBSD 上,调用 returns 立即出现 EPERM 错误代码。
pthread_condition_timedwait.cpp
#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
void *thread_handler(void *ptr){
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
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_t thread;
// start the thread
pthread_create(&thread, NULL, &thread_handler, NULL);
// wait for thread to finish
pthread_join(thread, NULL);
return 0;
}
如果调用 timedwait 的线程不拥有互斥锁,则返回 EPERM。您必须在调用 timedwait 之前锁定互斥量。此外,将 mutex 和 condvar 的静态初始化移动到文件范围。
更新:如果将互斥锁初始化为错误检查互斥锁,Linux 也将以 EPERM 终止(因为在不持有互斥锁的情况下调用 pthread_cond_wait/timedwait 是 UB)。
修改后的代码如下:
//#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;
}
在内核 SMP Debian 4.9.82-1+deb9u3 (2018-03-02) x86_64 GNU/Linux, distro Debian GNU/Linux buster/sid.
我有一个创建 pthread 的示例程序,等待线程加入。线程将调用 phread_cond_timedwait() 等待 2 秒。在 Linux 平台上,示例代码运行良好。在 FreeBSD 上,调用 returns 立即出现 EPERM 错误代码。
pthread_condition_timedwait.cpp
#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
void *thread_handler(void *ptr){
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
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_t thread;
// start the thread
pthread_create(&thread, NULL, &thread_handler, NULL);
// wait for thread to finish
pthread_join(thread, NULL);
return 0;
}
如果调用 timedwait 的线程不拥有互斥锁,则返回 EPERM。您必须在调用 timedwait 之前锁定互斥量。此外,将 mutex 和 condvar 的静态初始化移动到文件范围。
更新:如果将互斥锁初始化为错误检查互斥锁,Linux 也将以 EPERM 终止(因为在不持有互斥锁的情况下调用 pthread_cond_wait/timedwait 是 UB)。
修改后的代码如下:
//#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;
}
在内核 SMP Debian 4.9.82-1+deb9u3 (2018-03-02) x86_64 GNU/Linux, distro Debian GNU/Linux buster/sid.