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:
committed by
Santiago Gimeno
parent
688666948e
commit
06d31638e2
@@ -333,16 +333,10 @@ void CardReader::HandleReaderStatusChange(uv_async_t *handle, int status) {
|
|||||||
|
|
||||||
AsyncResult* ar = async_baton->async_result;
|
AsyncResult* ar = async_baton->async_result;
|
||||||
|
|
||||||
if (ar->do_exit) {
|
if (reader->m_state == 1) {
|
||||||
uv_close(reinterpret_cast<uv_handle_t*>(&async_baton->async), CloseCallback); // necessary otherwise UV will block
|
// Swallow events : Listening thread was cancelled by user.
|
||||||
|
} else if ((ar->result == SCARD_S_SUCCESS) ||
|
||||||
/* Emit end event */
|
(ar->result == (LONG)SCARD_E_NO_READERS_AVAILABLE)) { // Card reader was unplugged, it's not an error
|
||||||
Local<Value> argv[1] = {
|
|
||||||
Nan::New("_end").ToLocalChecked(), // event name
|
|
||||||
};
|
|
||||||
|
|
||||||
Nan::MakeCallback(async_baton->reader->handle(), "emit", 1, argv);
|
|
||||||
} else {
|
|
||||||
if (ar->result == SCARD_S_SUCCESS) {
|
if (ar->result == SCARD_S_SUCCESS) {
|
||||||
const unsigned argc = 3;
|
const unsigned argc = 3;
|
||||||
Local<Value> argv[argc] = {
|
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) {
|
if (reader->m_status_thread) {
|
||||||
uv_mutex_unlock(&reader->m_mutex);
|
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.szReader = reader->m_name.c_str();
|
||||||
card_reader_state.dwCurrentState = SCARD_STATE_UNAWARE;
|
card_reader_state.dwCurrentState = SCARD_STATE_UNAWARE;
|
||||||
|
|
||||||
bool keep_watching(result == SCARD_S_SUCCESS);
|
while (!reader->m_state) {
|
||||||
while (keep_watching) {
|
|
||||||
|
|
||||||
result = SCardGetStatusChange(reader->m_status_card_context, INFINITE, &card_reader_state, 1);
|
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);
|
uv_mutex_lock(&reader->m_mutex);
|
||||||
if (reader->m_state == 1) {
|
if (reader->m_state == 1) {
|
||||||
|
// Exit requested by user. Notify close method about SCardStatusChange was interrupted.
|
||||||
uv_cond_signal(&reader->m_cond);
|
uv_cond_signal(&reader->m_cond);
|
||||||
}
|
} else if (result != (LONG)SCARD_S_SUCCESS) {
|
||||||
|
// Exit this loop due to errors
|
||||||
if (!keep_watching) {
|
|
||||||
reader->m_state = 2;
|
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->result = result;
|
||||||
async_baton->async_result->status = card_reader_state.dwEventState;
|
async_baton->async_result->status = card_reader_state.dwEventState;
|
||||||
memcpy(async_baton->async_result->atr, card_reader_state.rgbAtr, card_reader_state.cbAtr);
|
memcpy(async_baton->async_result->atr, card_reader_state.rgbAtr, card_reader_state.cbAtr);
|
||||||
async_baton->async_result->atrlen = 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);
|
uv_async_send(&async_baton->async);
|
||||||
card_reader_state.dwCurrentState = card_reader_state.dwEventState;
|
card_reader_state.dwCurrentState = card_reader_state.dwEventState;
|
||||||
}
|
}
|
||||||
|
|
||||||
async_baton->async_result->do_exit = true;
|
// Exit flag set in keepwatching and handled in following uv_async_send
|
||||||
uv_async_send(&async_baton->async);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardReader::DoConnect(uv_work_t* req) {
|
void CardReader::DoConnect(uv_work_t* req) {
|
||||||
|
|||||||
@@ -124,12 +124,10 @@ void PCSCLite::HandleReaderStatusChange(uv_async_t *handle, int status) {
|
|||||||
AsyncBaton* async_baton = static_cast<AsyncBaton*>(handle->data);
|
AsyncBaton* async_baton = static_cast<AsyncBaton*>(handle->data);
|
||||||
AsyncResult* ar = async_baton->async_result;
|
AsyncResult* ar = async_baton->async_result;
|
||||||
|
|
||||||
if (ar->do_exit) {
|
if (async_baton->pcsclite->m_state == 1) {
|
||||||
uv_close(reinterpret_cast<uv_handle_t*>(&async_baton->async), CloseCallback); // necessary otherwise UV will block
|
// Swallow events : Listening thread was cancelled by user.
|
||||||
return;
|
} else if ((ar->result == SCARD_S_SUCCESS) ||
|
||||||
}
|
(ar->result == (LONG)SCARD_E_NO_READERS_AVAILABLE)) {
|
||||||
|
|
||||||
if ((ar->result == SCARD_S_SUCCESS) || (ar->result == (LONG)SCARD_E_NO_READERS_AVAILABLE)) {
|
|
||||||
const unsigned argc = 2;
|
const unsigned argc = 2;
|
||||||
Local<Value> argv[argc] = {
|
Local<Value> argv[argc] = {
|
||||||
Nan::Undefined(), // argument
|
Nan::Undefined(), // argument
|
||||||
@@ -145,6 +143,13 @@ void PCSCLite::HandleReaderStatusChange(uv_async_t *handle, int status) {
|
|||||||
Nan::Callback(Nan::New(async_baton->callback)).Call(argc, argv);
|
Nan::Callback(Nan::New(async_baton->callback)).Call(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do exit, after throwing last events
|
||||||
|
if (ar->do_exit) {
|
||||||
|
// necessary otherwise UV will block
|
||||||
|
uv_close(reinterpret_cast<uv_handle_t*>(&async_baton->async), CloseCallback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* reset AsyncResult */
|
/* reset AsyncResult */
|
||||||
delete [] ar->readers_name;
|
delete [] ar->readers_name;
|
||||||
ar->readers_name = NULL;
|
ar->readers_name = NULL;
|
||||||
@@ -159,7 +164,7 @@ void PCSCLite::HandlerFunction(void* arg) {
|
|||||||
PCSCLite* pcsclite = async_baton->pcsclite;
|
PCSCLite* pcsclite = async_baton->pcsclite;
|
||||||
async_baton->async_result = new AsyncResult();
|
async_baton->async_result = new AsyncResult();
|
||||||
|
|
||||||
while (!pcsclite->m_state && (result == SCARD_S_SUCCESS)) {
|
while (!pcsclite->m_state) {
|
||||||
/* Get card readers */
|
/* Get card readers */
|
||||||
result = pcsclite->get_card_readers(pcsclite, async_baton->async_result);
|
result = pcsclite->get_card_readers(pcsclite, async_baton->async_result);
|
||||||
if (result == (LONG)SCARD_E_NO_READERS_AVAILABLE) {
|
if (result == (LONG)SCARD_E_NO_READERS_AVAILABLE) {
|
||||||
@@ -180,6 +185,7 @@ void PCSCLite::HandlerFunction(void* arg) {
|
|||||||
INFINITE,
|
INFINITE,
|
||||||
&pcsclite->m_card_reader_state,
|
&pcsclite->m_card_reader_state,
|
||||||
1);
|
1);
|
||||||
|
|
||||||
uv_mutex_lock(&pcsclite->m_mutex);
|
uv_mutex_lock(&pcsclite->m_mutex);
|
||||||
if (pcsclite->m_state) {
|
if (pcsclite->m_state) {
|
||||||
uv_cond_signal(&pcsclite->m_cond);
|
uv_cond_signal(&pcsclite->m_cond);
|
||||||
@@ -190,9 +196,12 @@ void PCSCLite::HandlerFunction(void* arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uv_mutex_unlock(&pcsclite->m_mutex);
|
uv_mutex_unlock(&pcsclite->m_mutex);
|
||||||
} else {
|
} else if (result == SCARD_S_SUCCESS) {
|
||||||
/* If PnP is not supported, just wait for 1 second */
|
/* If PnP is not supported, just wait for 1 second */
|
||||||
Sleep(1000);
|
Sleep(1000);
|
||||||
|
} else {
|
||||||
|
/* Error on last card access and no PnP, stop monitoring */
|
||||||
|
pcsclite->m_state = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user