Martin Paljak wrote:
On Apr 14, 2010, at 19:28 , Viktor TARASOV wrote:
Hi,
I'm testing the OpenSC pkcs11 module with Firefox.
In the logs I see the endless loop of the messages from the
C_WaitForSlotEvent() and underneath calls,
non interrupted by timeout. CPU usage is considerable.
My question: should it be like this?
No. I've said before that (blocking) C_WaitForSlotEvent is broken (by me) in
trunk.
This patch is 'working for me'.
It was applied to the IAS/ECC branch and tested in WinXP SP3.
If no objections, I'll apply it to the trunk.
Kind wishes,
Viktor.
--
Viktor Tarasov <viktor.tara...@opentrust.com>
Index: opensc.trunk/src/tools/util.c
===================================================================
--- opensc.trunk/src/tools/util.c (révision 4343)
+++ opensc.trunk/src/tools/util.c (copie de travail)
@@ -23,7 +23,7 @@
if (sc_ctx_get_reader_count(ctx) == 0) {
fprintf(stderr, "Waiting for a reader to be attached...\n");
- r = sc_wait_for_event(ctx, SC_EVENT_READER_ATTACHED, &found, &event, -1);
+ r = sc_wait_for_event(ctx, SC_EVENT_READER_ATTACHED, &found, &event, -1, NULL);
if (r < 0) {
fprintf(stderr, "Error while waiting for a reader: %s\n", sc_strerror(r));
return 3;
@@ -35,7 +35,7 @@
}
}
fprintf(stderr, "Waiting for a card to be inserted...\n");
- r = sc_wait_for_event(ctx, SC_EVENT_CARD_INSERTED, &found, &event, -1);
+ r = sc_wait_for_event(ctx, SC_EVENT_CARD_INSERTED, &found, &event, -1, NULL);
if (r < 0) {
fprintf(stderr, "Error while waiting for a card: %s\n", sc_strerror(r));
return 3;
Index: opensc.trunk/src/pkcs11/pkcs11-global.c
===================================================================
--- opensc.trunk/src/pkcs11/pkcs11-global.c (révision 4343)
+++ opensc.trunk/src/pkcs11/pkcs11-global.c (copie de travail)
@@ -608,13 +608,14 @@
CK_VOID_PTR pReserved) /* reserved. Should be NULL_PTR */
{
sc_reader_t *found;
- int r;
unsigned int mask, events;
+ void *reader_states = NULL;
+ CK_SLOT_ID slot_id;
CK_RV rv;
+ int ii, r;
- if (pReserved != NULL_PTR) {
+ if (pReserved != NULL_PTR)
return CKR_ARGUMENTS_BAD;
- }
sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_WaitForSlotEvent(block=%d)", !(flags & CKF_DONT_BLOCK));
#if 0
@@ -633,21 +634,25 @@
mask |= SC_EVENT_READER_EVENTS;
}
- if ((rv = slot_find_changed(pSlot, mask)) == CKR_OK
- || (flags & CKF_DONT_BLOCK))
+ rv = slot_find_changed(&slot_id, mask);
+ if ((rv == CKR_OK) || (flags & CKF_DONT_BLOCK))
goto out;
again:
+ sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_WaitForSlotEvent() reader_states:%p", reader_states);
sc_pkcs11_unlock();
- r = sc_wait_for_event(context, mask, &found, &events, -1);
-
+ r = sc_wait_for_event(context, mask, &found, &events, -1, &reader_states);
if (sc_pkcs11_conf.plug_and_play && events & SC_EVENT_READER_ATTACHED) {
/* NSS/Firefox Triggers a C_GetSlotList(NULL) only if a slot ID is returned that it does not know yet
Change the first hotplug slot id on every call to make this happen.
*/
sc_pkcs11_slot_t *hotplug_slot = list_get_at(&virtual_slots, 0);
*pSlot= hotplug_slot->id -1;
- rv = CKR_OK;
+
+ rv = sc_pkcs11_lock();
+ if (rv != CKR_OK)
+ return rv;
+
goto out;
}
/* Was C_Finalize called ? */
@@ -665,10 +670,21 @@
/* If no changed slot was found (maybe an unsupported card
* was inserted/removed) then go waiting again */
- if ((rv = slot_find_changed(pSlot, mask)) != CKR_OK)
+ rv = slot_find_changed(&slot_id, mask);
+ if (rv != CKR_OK)
goto again;
-out: sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_WaitForSlotEvent() = %s, event in 0x%lx", lookup_enum (RV_T, rv), *pSlot);
+out:
+ if (pSlot)
+ *pSlot = slot_id;
+
+ /* Free allocated readers states holder */
+ if (reader_states) {
+ sc_debug(context, SC_LOG_DEBUG_NORMAL, "free reader states");
+ sc_wait_for_event(context, 0, NULL, NULL, -1, &reader_states);
+ }
+
+ sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_WaitForSlotEvent() = %s, event in 0x%lx", lookup_enum (RV_T, rv), *pSlot);
sc_pkcs11_unlock();
return rv;
}
Index: opensc.trunk/src/libopensc/reader-pcsc.c
===================================================================
--- opensc.trunk/src/libopensc/reader-pcsc.c (révision 4343)
+++ opensc.trunk/src/libopensc/reader-pcsc.c (copie de travail)
@@ -953,11 +953,9 @@
/* Wait for an event to occur.
*/
-static int pcsc_wait_for_event(sc_context_t *ctx,
- void *reader_data,
- unsigned int event_mask,
- sc_reader_t **event_reader,
- unsigned int *event, int timeout)
+static int pcsc_wait_for_event(sc_context_t *ctx, void *reader_data,
+ unsigned int event_mask, sc_reader_t **event_reader, unsigned int *event,
+ int timeout, void **reader_states)
{
struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *)reader_data;
LONG rv;
@@ -968,26 +966,40 @@
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL);
- rgReaderStates = (SCARD_READERSTATE_A *) calloc(sc_ctx_get_reader_count(ctx) + 1, sizeof(SCARD_READERSTATE_A));
- if (!rgReaderStates)
- return SC_ERROR_OUT_OF_MEMORY;
+ if (!event_reader && !event && reader_states) {
+ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "free allocated reader states");
+ free(*reader_states);
+ *reader_states = NULL;
+ SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
+ }
- /* Find out the current status */
- num_watch = sc_ctx_get_reader_count(ctx);
- sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Trying to watch %d readers", num_watch);
- for (i = 0; i < num_watch; i++) {
- rgReaderStates[i].szReader = sc_ctx_get_reader(ctx, i)->name;
- rgReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE;
- rgReaderStates[i].dwEventState = SCARD_STATE_UNAWARE;
- }
+ if (reader_states == NULL || *reader_states == NULL) {
+ rgReaderStates = (SCARD_READERSTATE_A *) calloc(sc_ctx_get_reader_count(ctx) + 2, sizeof(SCARD_READERSTATE_A));
+ if (!rgReaderStates)
+ SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY);
+
+ /* Find out the current status */
+ num_watch = sc_ctx_get_reader_count(ctx);
+ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Trying to watch %d readers", num_watch);
+ for (i = 0; i < num_watch; i++) {
+ rgReaderStates[i].szReader = sc_ctx_get_reader(ctx, i)->name;
+ rgReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE;
+ rgReaderStates[i].dwEventState = SCARD_STATE_UNAWARE;
+ }
#ifndef __APPLE__ /* OS X 10.6.2 does not support PnP notification */
- if (event_mask & SC_EVENT_READER_ATTACHED) {
- rgReaderStates[i].szReader = "\\\\?PnP?\\Notification";
- rgReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE;
- rgReaderStates[i].dwEventState = SCARD_STATE_UNAWARE;
- num_watch++;
+ if (event_mask & SC_EVENT_READER_ATTACHED) {
+ rgReaderStates[i].szReader = "\\\\?PnP?\\Notification";
+ rgReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE;
+ rgReaderStates[i].dwEventState = SCARD_STATE_UNAWARE;
+ num_watch++;
+ }
+#endif
}
-#endif
+ else {
+ rgReaderStates = (SCARD_READERSTATE_A *)(*reader_states);
+ for (num_watch = 0; rgReaderStates[num_watch].szReader; num_watch++)
+ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "re-use reader '%s'", rgReaderStates[num_watch].szReader);
+ }
#ifndef _WIN32
/* Establish a new context, assuming that it is called from a different thread with pcsc-lite */
if (gpriv->pcsc_wait_ctx == -1) {
@@ -1028,9 +1040,11 @@
*event = 0;
for (i = 0, rsp = rgReaderStates; i < num_watch; i++, rsp++) {
unsigned long state, prev_state;
- sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "%s before=0x%04X now=0x%04X", rsp->szReader, rsp->dwCurrentState, rsp->dwEventState);
+ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "'%s' before=0x%04X now=0x%04X", rsp->szReader,
+ rsp->dwCurrentState, rsp->dwEventState);
prev_state = rsp->dwCurrentState;
state = rsp->dwEventState;
+ rsp->dwCurrentState = rsp->dwEventState;
if (state & SCARD_STATE_CHANGED) {
/* check for hotplug events */
@@ -1065,14 +1079,13 @@
*event_reader = sc_ctx_get_reader_by_name(ctx, rsp->szReader);
r = SC_SUCCESS;
goto out;
- SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
}
}
/* No match - copy the state so pcscd knows
* what to watch out for */
- rsp->dwCurrentState = rsp->dwEventState;
+ //rsp->dwCurrentState = rsp->dwEventState;
}
if (timeout == 0) {
@@ -1085,7 +1098,6 @@
timeout = INFINITE;
}
- sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Sleeping call, timeout 0x%lx", timeout);
rv = gpriv->SCardGetStatusChange(gpriv->pcsc_wait_ctx, timeout, rgReaderStates, num_watch);
if (rv == (LONG) SCARD_E_CANCELLED) {
@@ -1106,7 +1118,14 @@
}
}
out:
- free(rgReaderStates);
+ if (!reader_states) {
+ free(rgReaderStates);
+ }
+ else if (*reader_states == NULL) {
+ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "return allocated 'reader states'");
+ *reader_states = rgReaderStates;
+ }
+
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r);
}
Index: opensc.trunk/src/libopensc/ctx.c
===================================================================
--- opensc.trunk/src/libopensc/ctx.c (révision 4343)
+++ opensc.trunk/src/libopensc/ctx.c (copie de travail)
@@ -781,16 +781,18 @@
}
-int sc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_reader_t **event_reader, unsigned int *event, int timeout)
+int sc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_reader_t **event_reader, unsigned int *event, int timeout,
+ void **reader_states)
{
int i;
const struct sc_reader_driver *driver;
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL);
for (i = 0; ctx->reader_drivers[i] != NULL; i++) {
- sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "trying %s", ctx->reader_drivers[i]->short_name);
+ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "trying to wait event from %s", ctx->reader_drivers[i]->short_name);
driver = ctx->reader_drivers[i];
if (driver->ops->wait_for_event != NULL)
- return driver->ops->wait_for_event(ctx, ctx->reader_drv_data[i], event_mask, event_reader, event, timeout);
+ return driver->ops->wait_for_event(ctx, ctx->reader_drv_data[i], event_mask, event_reader, event, timeout,
+ reader_states);
}
return SC_ERROR_NOT_SUPPORTED;
}
Index: opensc.trunk/src/libopensc/opensc.h
===================================================================
--- opensc.trunk/src/libopensc/opensc.h (révision 4343)
+++ opensc.trunk/src/libopensc/opensc.h (copie de travail)
@@ -396,7 +396,9 @@
int (*perform_verify)(struct sc_reader *, struct sc_pin_cmd_data *);
/* Wait for an event */
- int (*wait_for_event)(struct sc_context *ctx, void *priv_data, unsigned int event_mask, sc_reader_t **event_reader, unsigned int *event, int timeout);
+ int (*wait_for_event)(struct sc_context *ctx, void *priv_data,
+ unsigned int event_mask, sc_reader_t **event_reader, unsigned int *event,
+ int timeout, void **reader_states);
/* Reset a reader */
int (*reset)(struct sc_reader *);
};
@@ -819,7 +821,8 @@
* @retval = 1 if the timeout occured
*/
int sc_wait_for_event(sc_context_t *ctx, unsigned int event_mask,
- sc_reader_t **event_reader, unsigned int *event, int timeout);
+ sc_reader_t **event_reader, unsigned int *event,
+ int timeout, void **reader_states);
/**
* Resets the card.
_______________________________________________
opensc-devel mailing list
opensc-devel@lists.opensc-project.org
http://www.opensc-project.org/mailman/listinfo/opensc-devel