A recent change causes SCardCancel() to block?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

A recent change causes SCardCancel() to block?

Ran Benita
Hello,

I have noticed a change in behavior in one of the recent pcsclite
releases. I am using pcsclite 1.8.21 and ccid 1.4.27 on ArchLinux.

The program below calls a blocking SCardGetStatusChange, but before that
spwans a thread which waits for a key press, then calls SCardCancel (on
the same context). It is a port of the Rust program here:
https://raw.githubusercontent.com/bluetech/pcsc-rust/01bd4d80e366ef00f7006dabee45c8cb356d8566/pcsc/examples/cancel.rs

Previously, the SCardCancel would return immediately and would cause
SCardGetStatusChange to return SCARD_E_CANCELLED immediately.

Now, SCardCancel blocks until SCardGetStatusChange times out, and only
then returns SCARD_S_SUCCESS.

Is this an intended change, or a regression? Or maybe I'm doing
something wrong?

Thanks,
Ran

// gcc -Wall -pthread $(pkg-config --libs --cflags libpcsclite) cancel.c -o cancel
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <pthread.h>

#include <PCSC/winscard.h>

static SCARDCONTEXT context;

static void *canceler_thread(void *arg) {
    LONG ret;

    getchar();

    printf("Calling SCardCancel...\n");
    ret = SCardCancel(context);
    assert(ret == SCARD_S_SUCCESS);
    printf("SCardCancel returned SCARD_S_SUCCESS\n");

    return NULL;
}

int main(void) {
    LONG ret;

    ret = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &context);
    assert(ret == SCARD_S_SUCCESS);

    // Spawn a thread which waits for a key-press then cancels the operation.
    pthread_t thread;
    ret = pthread_create(&thread, NULL, canceler_thread, NULL);

    // Set up the blocking call, and wait for cancel or timeout.
    printf("Entering blocking call; press Enter to cancel\n");
    SCARD_READERSTATE reader_states[] = {
        {
            .szReader = "\\\\?PnP?\\Notification",
            .pvUserData = NULL,
            .dwCurrentState = SCARD_STATE_UNAWARE,
            .dwEventState = SCARD_STATE_UNAWARE,
        },
    };

    ret = SCardGetStatusChange(context, 5000, reader_states, 1);
    switch (ret) {
    case SCARD_S_SUCCESS:
        printf("Blocking call exited normally\n");
        break;

    case SCARD_E_CANCELLED:
        printf("Blocking call canceled\n");
        break;

    case SCARD_E_TIMEOUT:
        printf("Blocking call timed out\n");
        break;

    default:
        fprintf(stderr, "Failed to get status changes: %ld", ret);
        break;
    }

    printf("Sleeping before existing main thread...\n");
    sleep(5);

    return 0;
}

_______________________________________________
Pcsclite-muscle mailing list
[hidden email]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pcsclite-muscle
Reply | Threaded
Open this post in threaded view
|

Re: A recent change causes SCardCancel() to block?

Frank Morgner-2
I'm observing the same issue with pcsc-lite version 1.8.16 in OpenSC, where we've activated a blocking SCardGetStatusChange recently. As a result, OpenSC currently stalls Firefox when the browser is closed or the module is unloaded. See also the OpenSC ticket.

Regards, Frank.

2017-06-14 11:43 GMT+02:00 Ran Benita <[hidden email]>:
Hello,

I have noticed a change in behavior in one of the recent pcsclite
releases. I am using pcsclite 1.8.21 and ccid 1.4.27 on ArchLinux.

The program below calls a blocking SCardGetStatusChange, but before that
spwans a thread which waits for a key press, then calls SCardCancel (on
the same context). It is a port of the Rust program here:
https://raw.githubusercontent.com/bluetech/pcsc-rust/01bd4d80e366ef00f7006dabee45c8cb356d8566/pcsc/examples/cancel.rs

Previously, the SCardCancel would return immediately and would cause
SCardGetStatusChange to return SCARD_E_CANCELLED immediately.

Now, SCardCancel blocks until SCardGetStatusChange times out, and only
then returns SCARD_S_SUCCESS.

Is this an intended change, or a regression? Or maybe I'm doing
something wrong?

Thanks,
Ran

// gcc -Wall -pthread $(pkg-config --libs --cflags libpcsclite) cancel.c -o cancel
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <pthread.h>

#include <PCSC/winscard.h>

static SCARDCONTEXT context;

static void *canceler_thread(void *arg) {
    LONG ret;

    getchar();

    printf("Calling SCardCancel...\n");
    ret = SCardCancel(context);
    assert(ret == SCARD_S_SUCCESS);
    printf("SCardCancel returned SCARD_S_SUCCESS\n");

    return NULL;
}

int main(void) {
    LONG ret;

    ret = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &context);
    assert(ret == SCARD_S_SUCCESS);

    // Spawn a thread which waits for a key-press then cancels the operation.
    pthread_t thread;
    ret = pthread_create(&thread, NULL, canceler_thread, NULL);

    // Set up the blocking call, and wait for cancel or timeout.
    printf("Entering blocking call; press Enter to cancel\n");
    SCARD_READERSTATE reader_states[] = {
        {
            .szReader = "\\\\?PnP?\\Notification",
            .pvUserData = NULL,
            .dwCurrentState = SCARD_STATE_UNAWARE,
            .dwEventState = SCARD_STATE_UNAWARE,
        },
    };

    ret = SCardGetStatusChange(context, 5000, reader_states, 1);
    switch (ret) {
    case SCARD_S_SUCCESS:
        printf("Blocking call exited normally\n");
        break;

    case SCARD_E_CANCELLED:
        printf("Blocking call canceled\n");
        break;

    case SCARD_E_TIMEOUT:
        printf("Blocking call timed out\n");
        break;

    default:
        fprintf(stderr, "Failed to get status changes: %ld", ret);
        break;
    }

    printf("Sleeping before existing main thread...\n");
    sleep(5);

    return 0;
}

_______________________________________________
Pcsclite-muscle mailing list
[hidden email]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pcsclite-muscle


_______________________________________________
Pcsclite-muscle mailing list
[hidden email]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pcsclite-muscle
Reply | Threaded
Open this post in threaded view
|

Re: A recent change causes SCardCancel() to block?

Ludovic Rousseau
In reply to this post by Ran Benita
2017-06-14 11:43 GMT+02:00 Ran Benita <[hidden email]>:
Hello,

Hello,
 

I have noticed a change in behavior in one of the recent pcsclite
releases. I am using pcsclite 1.8.21 and ccid 1.4.27 on ArchLinux.

The program below calls a blocking SCardGetStatusChange, but before that
spwans a thread which waits for a key press, then calls SCardCancel (on
the same context). It is a port of the Rust program here:
https://raw.githubusercontent.com/bluetech/pcsc-rust/01bd4d80e366ef00f7006dabee45c8cb356d8566/pcsc/examples/cancel.rs

Previously, the SCardCancel would return immediately and would cause
SCardGetStatusChange to return SCARD_E_CANCELLED immediately.

Now, SCardCancel blocks until SCardGetStatusChange times out, and only
then returns SCARD_S_SUCCESS.

Is this an intended change, or a regression? Or maybe I'm doing
something wrong?

No. Your sample code is correct.
The bug is in pcsc-lite since 1.8.21 (latest version).
More precisely at this line: https://github.com/LudovicRousseau/PCSC/commit/9a21c82330fc4b73ac00faf2c5cf948da5f8ab07#diff-320fdf2286b77c3aa12e4f0c174a5ac1L3082

I will release a new pcsc-lite soon.

Thanks for the bug report.
Bye

--
 Dr. Ludovic Rousseau

_______________________________________________
Pcsclite-muscle mailing list
[hidden email]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pcsclite-muscle