src: handle last event before exit status threads

- Avoid 2 consecutive calls to uv_async_send when exiting the cardreader.cpp
  check status thread.
- Fix mutex unlock location in cardreader.cpp check status thread.

PR-URL: https://github.com/santigimeno/node-pcsclite/pull/46
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
This commit is contained in:
Florian Ramillien
2015-12-22 10:58:35 +01:00
committed by Santiago Gimeno
parent 688666948e
commit 06d31638e2
2 changed files with 41 additions and 28 deletions

View File

@@ -333,16 +333,10 @@ void CardReader::HandleReaderStatusChange(uv_async_t *handle, int status) {
AsyncResult* ar = async_baton->async_result;
if (ar->do_exit) {
uv_close(reinterpret_cast<uv_handle_t*>(&async_baton->async), CloseCallback); // necessary otherwise UV will block
/* Emit end event */
Local<Value> argv[1] = {
Nan::New("_end").ToLocalChecked(), // event name
};
Nan::MakeCallback(async_baton->reader->handle(), "emit", 1, argv);
} else {
if (reader->m_state == 1) {
// Swallow events : Listening thread was cancelled by user.
} else if ((ar->result == SCARD_S_SUCCESS) ||
(ar->result == (LONG)SCARD_E_NO_READERS_AVAILABLE)) { // Card reader was unplugged, it's not an error
if (ar->result == SCARD_S_SUCCESS) {
const unsigned argc = 3;
Local<Value> argv[argc] = {
@@ -361,6 +355,17 @@ void CardReader::HandleReaderStatusChange(uv_async_t *handle, int status) {
}
}
if (ar->do_exit) {
uv_close(reinterpret_cast<uv_handle_t*>(&async_baton->async), CloseCallback); // necessary otherwise UV will block
/* Emit end event */
Local<Value> argv[1] = {
Nan::New("_end").ToLocalChecked(), // event name
};
Nan::MakeCallback(async_baton->reader->handle(), "emit", 1, argv);
}
if (reader->m_status_thread) {
uv_mutex_unlock(&reader->m_mutex);
}
@@ -379,33 +384,32 @@ void CardReader::HandlerFunction(void* arg) {
card_reader_state.szReader = reader->m_name.c_str();
card_reader_state.dwCurrentState = SCARD_STATE_UNAWARE;
bool keep_watching(result == SCARD_S_SUCCESS);
while (keep_watching) {
while (!reader->m_state) {
result = SCardGetStatusChange(reader->m_status_card_context, INFINITE, &card_reader_state, 1);
keep_watching = (result == SCARD_S_SUCCESS) && (!reader->m_state);
uv_mutex_lock(&reader->m_mutex);
if (reader->m_state == 1) {
// Exit requested by user. Notify close method about SCardStatusChange was interrupted.
uv_cond_signal(&reader->m_cond);
}
if (!keep_watching) {
} else if (result != (LONG)SCARD_S_SUCCESS) {
// Exit this loop due to errors
reader->m_state = 2;
}
uv_mutex_unlock(&reader->m_mutex);
async_baton->async_result->do_exit = (reader->m_state != 0);
async_baton->async_result->result = result;
async_baton->async_result->status = card_reader_state.dwEventState;
memcpy(async_baton->async_result->atr, card_reader_state.rgbAtr, card_reader_state.cbAtr);
async_baton->async_result->atrlen = card_reader_state.cbAtr;
uv_mutex_unlock(&reader->m_mutex);
uv_async_send(&async_baton->async);
card_reader_state.dwCurrentState = card_reader_state.dwEventState;
}
async_baton->async_result->do_exit = true;
uv_async_send(&async_baton->async);
// Exit flag set in keepwatching and handled in following uv_async_send
}
void CardReader::DoConnect(uv_work_t* req) {