Commit 3658b2b5 authored by Ryan Hileman's avatar Ryan Hileman Committed by Luca Boccassi

Problem: pthread condvar timeouts are broken (#2967)

* fix pthread condvar timeouts

This fixes a race condition / hang for threadsafe sockets.
Context: https://github.com/zeromq/czmq/issues/1873#issuecomment-370279244
parent d54633ad
...@@ -174,6 +174,13 @@ class condition_variable_t ...@@ -174,6 +174,13 @@ class condition_variable_t
#include <pthread.h> #include <pthread.h>
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
#define ANDROID_LEGACY
extern "C" int pthread_cond_timedwait_monotonic_np (pthread_cond_t *,
pthread_mutex_t *,
const struct timespec *);
#endif
namespace zmq namespace zmq
{ {
class condition_variable_t class condition_variable_t
...@@ -181,7 +188,12 @@ class condition_variable_t ...@@ -181,7 +188,12 @@ class condition_variable_t
public: public:
inline condition_variable_t () inline condition_variable_t ()
{ {
int rc = pthread_cond_init (&cond, NULL); pthread_condattr_t attr;
pthread_condattr_init (&attr);
#if !defined(ZMQ_HAVE_OSX) && !defined(ANDROID_LEGACY)
pthread_condattr_setclock (&attr, CLOCK_MONOTONIC);
#endif
int rc = pthread_cond_init (&cond, &attr);
posix_assert (rc); posix_assert (rc);
} }
...@@ -198,9 +210,9 @@ class condition_variable_t ...@@ -198,9 +210,9 @@ class condition_variable_t
if (timeout_ != -1) { if (timeout_ != -1) {
struct timespec timeout; struct timespec timeout;
#if defined ZMQ_HAVE_OSX \ #ifdef ZMQ_HAVE_OSX
&& __MAC_OS_X_VERSION_MIN_REQUIRED < 101200 // less than macOS 10.12 timeout.tv_sec = 0;
alt_clock_gettime (SYSTEM_CLOCK, &timeout); timeout.tv_nsec = 0;
#else #else
clock_gettime (CLOCK_MONOTONIC, &timeout); clock_gettime (CLOCK_MONOTONIC, &timeout);
#endif #endif
...@@ -212,8 +224,15 @@ class condition_variable_t ...@@ -212,8 +224,15 @@ class condition_variable_t
timeout.tv_sec++; timeout.tv_sec++;
timeout.tv_nsec -= 1000000000; timeout.tv_nsec -= 1000000000;
} }
#ifdef ZMQ_HAVE_OSX
rc = pthread_cond_timedwait_relative_np (
&cond, mutex_->get_mutex (), &timeout);
#elif defined(ANDROID_LEGACY)
rc = pthread_cond_timedwait_monotonic_np (
&cond, mutex_->get_mutex (), &timeout);
#else
rc = pthread_cond_timedwait (&cond, mutex_->get_mutex (), &timeout); rc = pthread_cond_timedwait (&cond, mutex_->get_mutex (), &timeout);
#endif
} else } else
rc = pthread_cond_wait (&cond, mutex_->get_mutex ()); rc = pthread_cond_wait (&cond, mutex_->get_mutex ());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment