Skip to content

Commit f7931a7

Browse files
committed
Return when C client worker threads fail to start
Signed-off-by: 1fanwang <1fannnw@gmail.com>
1 parent 7af463e commit f7931a7

2 files changed

Lines changed: 116 additions & 6 deletions

File tree

zookeeper-client/zookeeper-client-c/src/mt_adaptor.c

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,17 +199,19 @@ void notify_thread_ready(zhandle_t* zh)
199199
{
200200
struct adaptor_threads* adaptor=zh->adaptor_priv;
201201
pthread_mutex_lock(&adaptor->lock);
202-
adaptor->threadsToWait--;
202+
if(adaptor->threadsToWait>0)
203+
adaptor->threadsToWait--;
203204
pthread_cond_broadcast(&adaptor->cond);
204205
while(adaptor->threadsToWait>0)
205206
pthread_cond_wait(&adaptor->cond,&adaptor->lock);
206207
pthread_mutex_unlock(&adaptor->lock);
207208
}
208209

209210

210-
void start_threads(zhandle_t* zh)
211+
int start_threads(zhandle_t* zh)
211212
{
212213
int rc = 0;
214+
int io_started = 0;
213215
struct adaptor_threads* adaptor=zh->adaptor_priv;
214216
pthread_cond_init(&adaptor->cond,0);
215217
pthread_mutex_init(&adaptor->lock,0);
@@ -220,15 +222,34 @@ void start_threads(zhandle_t* zh)
220222
api_prolog(zh);
221223
LOG_DEBUG(LOGCALLBACK(zh), "starting threads...");
222224
rc=pthread_create(&adaptor->io, 0, do_io, zh);
223-
assert("pthread_create() failed for the IO thread"&&!rc);
225+
if(rc)
226+
goto fail;
227+
io_started=1;
224228
rc=pthread_create(&adaptor->completion, 0, do_completion, zh);
225-
assert("pthread_create() failed for the completion thread"&&!rc);
229+
if(rc)
230+
goto fail;
226231
wait_for_others(zh);
227-
api_epilog(zh, 0);
232+
api_epilog(zh, 0);
233+
return 0;
234+
235+
fail:
236+
LOG_ERROR(LOGCALLBACK(zh), "pthread_create() failed: %d", rc);
237+
if(io_started) {
238+
zh->close_requested=1;
239+
pthread_mutex_lock(&adaptor->lock);
240+
adaptor->threadsToWait=0;
241+
pthread_cond_broadcast(&adaptor->cond);
242+
pthread_mutex_unlock(&adaptor->lock);
243+
pthread_join(adaptor->io, 0);
244+
zh->close_requested=0;
245+
}
246+
api_epilog(zh, 0);
247+
return rc;
228248
}
229249

230250
int adaptor_init(zhandle_t *zh)
231251
{
252+
int rc;
232253
pthread_mutexattr_t recursive_mx_attr;
233254
struct adaptor_threads *adaptor_threads = calloc(1, sizeof(*adaptor_threads));
234255
if (!adaptor_threads) {
@@ -267,7 +288,12 @@ int adaptor_init(zhandle_t *zh)
267288
pthread_cond_init(&zh->sent_requests.cond,0);
268289
pthread_mutex_init(&zh->completions_to_process.lock,0);
269290
pthread_cond_init(&zh->completions_to_process.cond,0);
270-
start_threads(zh);
291+
rc=start_threads(zh);
292+
if(rc) {
293+
adaptor_destroy(zh);
294+
errno=rc;
295+
return -1;
296+
}
271297
return 0;
272298
}
273299

@@ -313,6 +339,8 @@ void adaptor_destroy(zhandle_t *zh)
313339
pthread_mutex_destroy(&zh->completions_to_process.lock);
314340
pthread_cond_destroy(&zh->completions_to_process.cond);
315341
pthread_mutex_destroy(&adaptor->zh_lock);
342+
pthread_mutex_destroy(&adaptor->reconfig_lock);
343+
pthread_mutex_destroy(&adaptor->watchers_lock);
316344

317345
pthread_mutex_destroy(&zh->auth_h.lock);
318346

zookeeper-client/zookeeper-client-c/tests/TestZookeeperInit.cc

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,63 @@ class MockPthreadsNull;
3333

3434
using namespace std;
3535

36+
#ifdef THREADED
37+
class CheckedPthreadCreateFailure : public CheckedPthread
38+
{
39+
public:
40+
explicit CheckedPthreadCreateFailure(int failOnCall):
41+
pthreadCreateCounter(0),pthreadJoinCounter(0),
42+
pthreadCondDestroyCounter(0),pthreadMutexDestroyCounter(0),
43+
threadCreated(false),failOnCall_(failOnCall){}
44+
45+
int pthread_create(pthread_t *t, const pthread_attr_t *a,
46+
void *(*f)(void *), void *d) override {
47+
if (pthreadCreateCounter++ == failOnCall_)
48+
return EAGAIN;
49+
int rc=CheckedPthread::pthread_create(t,a,f,d);
50+
if(!rc) {
51+
thread=*t;
52+
threadCreated=true;
53+
}
54+
return rc;
55+
}
56+
57+
int pthread_join(pthread_t t, void **r) override {
58+
pthreadJoinCounter++;
59+
return CheckedPthread::pthread_join(t,r);
60+
}
61+
62+
int pthread_cond_destroy(pthread_cond_t *c) override {
63+
pthreadCondDestroyCounter++;
64+
return CheckedPthread::pthread_cond_destroy(c);
65+
}
66+
67+
int pthread_mutex_destroy(pthread_mutex_t *m) override {
68+
pthreadMutexDestroyCounter++;
69+
return CheckedPthread::pthread_mutex_destroy(m);
70+
}
71+
72+
int pthreadCreateCounter;
73+
int pthreadJoinCounter;
74+
int pthreadCondDestroyCounter;
75+
int pthreadMutexDestroyCounter;
76+
pthread_t thread;
77+
bool threadCreated;
78+
79+
private:
80+
int failOnCall_;
81+
};
82+
#endif
83+
3684
class Zookeeper_init : public CPPUNIT_NS::TestFixture
3785
{
3886
CPPUNIT_TEST_SUITE(Zookeeper_init);
3987
CPPUNIT_TEST(testVersion);
4088
CPPUNIT_TEST(testBasic);
89+
#ifdef THREADED
90+
CPPUNIT_TEST(testFirstThreadCreateFailure);
91+
CPPUNIT_TEST(testSecondThreadCreateFailure);
92+
#endif
4193
CPPUNIT_TEST(testAddressResolution);
4294
CPPUNIT_TEST(testMultipleAddressResolution);
4395
CPPUNIT_TEST(testNullAddressString);
@@ -139,6 +191,36 @@ class Zookeeper_init : public CPPUNIT_NS::TestFixture
139191
CPPUNIT_ASSERT(MockPthreadsNull::isInitialized(&zh->completions_to_process.cond));
140192
#endif
141193
}
194+
#ifdef THREADED
195+
void assertThreadCreateFailure(int failOnCall)
196+
{
197+
delete pthreadMock;
198+
pthreadMock=0;
199+
CheckedPthreadCreateFailure pthreadFailure(failOnCall);
200+
201+
errno=0;
202+
zh=zookeeper_init("127.0.0.1:2121",watcher,10000,0,0,0);
203+
204+
CPPUNIT_ASSERT(zh==0);
205+
CPPUNIT_ASSERT_EQUAL(EAGAIN,errno);
206+
CPPUNIT_ASSERT_EQUAL(failOnCall+1,pthreadFailure.pthreadCreateCounter);
207+
CPPUNIT_ASSERT_EQUAL(failOnCall,pthreadFailure.pthreadJoinCounter);
208+
CPPUNIT_ASSERT_EQUAL(3,pthreadFailure.pthreadCondDestroyCounter);
209+
CPPUNIT_ASSERT_EQUAL(9,pthreadFailure.pthreadMutexDestroyCounter);
210+
if(pthreadFailure.threadCreated)
211+
CPPUNIT_ASSERT(CheckedPthread::isDestroyed(pthreadFailure.thread));
212+
}
213+
214+
void testFirstThreadCreateFailure()
215+
{
216+
assertThreadCreateFailure(0);
217+
}
218+
219+
void testSecondThreadCreateFailure()
220+
{
221+
assertThreadCreateFailure(1);
222+
}
223+
#endif
142224
void testAddressResolution()
143225
{
144226
const char EXPECTED_IPS[][4]={{127,0,0,1}};

0 commit comments

Comments
 (0)