src: multiple thread synchronization improvements
- Allow up to 4 the number of times SCardCancel is called before waiting for the status `thread` to finish. - Destroy the mutexes and conds only in the destructors. - Check that the thread handles are still valid before calling join on them.
This commit is contained in:
@@ -68,14 +68,16 @@ CardReader::CardReader(const std::string &reader_name): m_card_context(0),
|
||||
}
|
||||
|
||||
CardReader::~CardReader() {
|
||||
SCardCancel(m_card_context);
|
||||
int ret = uv_thread_join(&m_status_thread);
|
||||
assert(ret == 0);
|
||||
if (m_status_thread) {
|
||||
SCardCancel(m_card_context);
|
||||
assert(uv_thread_join(&m_status_thread) == 0);
|
||||
}
|
||||
|
||||
if (m_card_context) {
|
||||
SCardReleaseContext(m_card_context);
|
||||
}
|
||||
|
||||
uv_cond_destroy(&m_cond);
|
||||
uv_mutex_destroy(&m_mutex);
|
||||
}
|
||||
|
||||
@@ -302,21 +304,23 @@ NAN_METHOD(CardReader::Close) {
|
||||
LONG result = SCARD_S_SUCCESS;
|
||||
CardReader* obj = Nan::ObjectWrap::Unwrap<CardReader>(info.This());
|
||||
|
||||
uv_mutex_lock(&obj->m_mutex);
|
||||
if (obj->m_state == 0) {
|
||||
obj->m_state = 1;
|
||||
do {
|
||||
result = SCardCancel(obj->m_status_card_context);
|
||||
} while (uv_cond_timedwait(&obj->m_cond, &obj->m_mutex, 10000000) != 0);
|
||||
if (obj->m_status_thread) {
|
||||
uv_mutex_lock(&obj->m_mutex);
|
||||
if (obj->m_state == 0) {
|
||||
int ret;
|
||||
int times = 0;
|
||||
obj->m_state = 1;
|
||||
do {
|
||||
result = SCardCancel(obj->m_status_card_context);
|
||||
ret = uv_cond_timedwait(&obj->m_cond, &obj->m_mutex, 10000000);
|
||||
} while ((ret != 0) && (++ times < 5));
|
||||
}
|
||||
|
||||
assert(uv_thread_join(&obj->m_status_thread) == 0);
|
||||
obj->m_status_thread = 0;
|
||||
uv_mutex_unlock(&obj->m_mutex);
|
||||
}
|
||||
|
||||
assert(uv_thread_join(&obj->m_status_thread) == 0);
|
||||
obj->m_status_thread = 0;
|
||||
|
||||
uv_mutex_unlock(&obj->m_mutex);
|
||||
uv_mutex_destroy(&obj->m_mutex);
|
||||
uv_cond_destroy(&obj->m_cond);
|
||||
|
||||
info.GetReturnValue().Set(Nan::New<Number>(result));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user