C API makes it difficult to implement a timed wait_until_connected method
correctly
-----------------------------------------------------------------------------------
Key: ZOOKEEPER-1446
URL: https://issues.apache.org/jira/browse/ZOOKEEPER-1446
Project: ZooKeeper
Issue Type: Bug
Components: c client
Affects Versions: 3.3.5, 3.4.3
Reporter: Stephen Tyree
Priority: Minor
When using the C API, one might feel inclined to create a
zookeeper_wait_until_connected method which waits for some amount for a
connected state event to occur. The code might look like the following (didn't
actually compile this):
//------
static pthread_mutex_t kConnectedMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t kConnectedCondvar = PTHREAD_COND_INITIALIZER;
int zookeeper_wait_until_connected(zhandle_t* zk, const struct timespec*
timeout)
{
struct timespec abstime;
clock_gettime(TIMER_ABSTIME, &abstime);
abstime->tv_sec += timeout->tv_sec;
abstime->tv_nsec += timeout->tv_nsec;
pthread_mutex_lock(&kConnectedMutex);
if (zoo_state(zk) == ZOO_CONNECTED_STATE) {
return 1;
}
pthread_cond_timedwait(&kConnectedCondvar, &kConnectedMutex, &abstime);
int state = zoo_state(zk);
return (state == ZOO_CONNECTED_STATE);
}
void zookeeper_session_callback(zhandle_t* zh, int type, int state, const char*
path, void* arg)
{
pthread_mutex_lock(&kConnectedMutex);
if (type == ZOO_SESSION_EVENT && state == ZOO_CONNECTED_STATE) {
pthread_cond_broadcast(&kConnectedCondvar);
}
}
//-----
That would work fine (assuming I didn't screw anything up), except that
pthread_cond_timedwait can spuriously wakeup, making you not actually wait the
desired timeout. The solution to this is to loop until the condition is met,
which might look like the following:
//---
int state = zoo_state(zk);
int result = 0;
while ((state == ZOO_CONNECTING_STATE || state == ZOO_ASSOCIATING_STATE) &&
result != ETIMEDOUT) {
result = pthread_cond_timedwait(&kConnectedCondvar, &kConnectedMutex,
&abstime);
state = zoo_state(zk);
}
//---
That would work fine, except the state might be valid and connecting, yet not
ZOO_CONNECTING_STATE or ZOO_ASSOCIATING_STATE, it might be 0 or, as implemented
recently courtesy of zookeeper-1108, 999. Checking for those states causes your
code to rely upon an implementation detail of zookeeper, a problem highlighted
by that implementation detail changing recently. Is there any way this behavior
can become documented (via a ZOO_INITIALIZED_STATE or something like that), or
is there any way this behavior can be supported by the library itself?
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators:
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira