From c83a39e10d01767268a1511c287cb851ed139efc Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Fri, 23 Sep 2016 13:13:58 +0200 Subject: [PATCH 1/4] src: fix deadlock in CardReader Move the `uv_mutex_unlock` before the `uv_thread_join` as it could perfectly lock with `CardReader::HandlerFunction` `uv_mutex_unlock`. --- src/cardreader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cardreader.cpp b/src/cardreader.cpp index 85e2ca7..56c3c6a 100644 --- a/src/cardreader.cpp +++ b/src/cardreader.cpp @@ -316,9 +316,9 @@ NAN_METHOD(CardReader::Close) { } while ((ret != 0) && (++ times < 5)); } + 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); } info.GetReturnValue().Set(Nan::New(result)); From 76a1c9a200962f07704cfa648bf8b22181dec071 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Fri, 23 Sep 2016 13:15:21 +0200 Subject: [PATCH 2/4] Version 0.4.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1d3cffb..6b0c3c6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pcsclite", - "version": "0.4.9", + "version": "0.4.10", "engines": { "node": ">=0.8.0 < 4" }, From c311ea038cc100f2d4f5702927bd6ca6f94133d1 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Thu, 24 Nov 2016 15:02:57 +0100 Subject: [PATCH 3/4] pcsclite: return SCardGetStatusChange errors So it's possible to know when and why pcsc stops watching for events. --- src/pcsclite.cpp | 61 +++++++++++++++++++++++++++--------------------- src/pcsclite.h | 1 + 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/pcsclite.cpp b/src/pcsclite.cpp index 42d9bbb..2c1358c 100644 --- a/src/pcsclite.cpp +++ b/src/pcsclite.cpp @@ -144,11 +144,8 @@ void PCSCLite::HandleReaderStatusChange(uv_async_t *handle, int status) { Nan::Callback(Nan::New(async_baton->callback)).Call(argc, argv); } else { - Local err = Nan::Error(error_msg("SCardListReaders", ar->result).c_str()); - // Prepare the parameters for the callback function. - const unsigned argc = 1; - Local argv[argc] = { err }; - Nan::Callback(Nan::New(async_baton->callback)).Call(argc, argv); + Local argv[1] = { Nan::Error(ar->err_msg.c_str()) }; + Nan::Callback(Nan::New(async_baton->callback)).Call(1, argv); } // Do exit, after throwing last events @@ -186,34 +183,44 @@ void PCSCLite::HandlerFunction(void* arg) { /* Store the result in the baton */ async_baton->async_result->result = result; + if (result != SCARD_S_SUCCESS) { + async_baton->async_result->err_msg = error_msg("SCardListReaders", + result); + } + /* Notify the nodejs thread */ uv_async_send(&async_baton->async); - if (pcsclite->m_pnp) { - /* Set current status */ - pcsclite->m_card_reader_state.dwCurrentState = - pcsclite->m_card_reader_state.dwEventState; - /* Start checking for status change */ - result = SCardGetStatusChange(pcsclite->m_card_context, - INFINITE, - &pcsclite->m_card_reader_state, - 1); + if (result == SCARD_S_SUCCESS) { + if (pcsclite->m_pnp) { + /* Set current status */ + pcsclite->m_card_reader_state.dwCurrentState = + pcsclite->m_card_reader_state.dwEventState; + /* Start checking for status change */ + result = SCardGetStatusChange(pcsclite->m_card_context, + INFINITE, + &pcsclite->m_card_reader_state, + 1); - uv_mutex_lock(&pcsclite->m_mutex); - if (pcsclite->m_state) { - uv_cond_signal(&pcsclite->m_cond); + uv_mutex_lock(&pcsclite->m_mutex); + async_baton->async_result->result = result; + if (pcsclite->m_state) { + uv_cond_signal(&pcsclite->m_cond); + } + + if (result != SCARD_S_SUCCESS) { + pcsclite->m_state = 2; + async_baton->async_result->err_msg = + error_msg("SCardGetStatusChange", result); + } + + uv_mutex_unlock(&pcsclite->m_mutex); + } else { + /* If PnP is not supported, just wait for 1 second */ + Sleep(1000); } - - if (result != SCARD_S_SUCCESS) { - pcsclite->m_state = 2; - } - - uv_mutex_unlock(&pcsclite->m_mutex); - } else if (result == SCARD_S_SUCCESS) { - /* If PnP is not supported, just wait for 1 second */ - Sleep(1000); } else { - /* Error on last card access and no PnP, stop monitoring */ + /* Error on last card access, stop monitoring */ pcsclite->m_state = 2; } } diff --git a/src/pcsclite.h b/src/pcsclite.h index 7ef962b..ca6696a 100644 --- a/src/pcsclite.h +++ b/src/pcsclite.h @@ -16,6 +16,7 @@ class PCSCLite: public Nan::ObjectWrap { LPSTR readers_name; DWORD readers_name_length; bool do_exit; + std::string err_msg; }; struct AsyncBaton { From 51e9db2ad6816d2ed51216e62b952fe72ecc09b6 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Thu, 24 Nov 2016 15:14:39 +0100 Subject: [PATCH 4/4] Version 0.4.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6b0c3c6..378254e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pcsclite", - "version": "0.4.10", + "version": "0.4.11", "engines": { "node": ">=0.8.0 < 4" },