waitForCardPresent() within thread freezes applet under Ubuntu
Hello,
I am currently having some issues with the waitForCardPresent() function in an applet.
I am developping an applet that manages PC/SC communications.
In my applet I need to check card Status.
To do I use a Thread , I have created a CardStatus class that manages the work of the thread (this class extends Thread).
Here is how I start my thread :
Code:
cs = new CardStatus();
cardStatusThread = new Thread(cs);
cardStatusThread.start();
I use EventListeners to notify my applet once waitForCardPresent() has finished.
The run() of my thread consists of (I have simplified the code) :
Code:
while(true)
{
if(Reader != null)
{
try {
if(!Reader.isCardPresent()) // the reader is set by the applet using a SetReader() function defined in CardStatus class
{
Reader.waitForCardPresent(0);
this.NotifyPresentListeners(); // this function notifies the applet that a card has been found
}
} catch (CardException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
This applet is signed.
I successfully manage to run this applet using windows, but I can't when using Ubuntu : the applet freezes until I put a card in the reader.
I have tried to replace the Reader.waitForCardPresent(0); instruction with Thread.sleep(50000); to check if there was a mistake from the way I was using my thread, in that case my applet doesn't freeze under Ubuntu ; so I am guessing that it is the waitForCardPresent function that causes the trouble.
I know that it could not be a security issue, because I have created an un signed applet that uses WaitForCardPresent (not within a thread, within the main code of the applet, just to test this) and I had no problem with it.
Last edited by emilie.c@pro-active.fr; April 21st, 2010 at 02:00 AM.
Reason: code tags
Re: waitForCardPresent() within thread freezes applet under Ubuntu
The CardTerminal.waitForCardPresent method (you didn't say, but I guess this is the one you mean) blocks indefinitely (until you put a card in) if you give it an argument of zero.
The outcome of any serious research can only be to make two questions grow where only one grew before...
T. Veblen
Please use [CODE]...your code here...[/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.
Re: waitForCardPresent() within thread freezes applet under Ubuntu
OK. Unfortunately I don't know how Ubuntu handles Java threading & blocking IO operations.
Perhaps someone with Ubuntu experience can help.
It's easy to cry "bug" when the truth is that you've got a complex system and sometimes it takes a while to get all the components to co-exist peacefully...
D. Vargas
Please use [CODE]...your code here...[/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.
Re: waitForCardPresent() within thread freezes applet under Ubuntu
You may want to check the CPU usage to check to see if the applet is freezing through the main thread being suspended/blocked or if it is because the background thread is using all the available CPU resources?
BTW you may want to put a short sleep in your while loop or better still call the waitForCardAbsent() method otherwise when the card is present your background thread is going to go around and around the loop chewing up CPU resources until the card is removed.
Re: waitForCardPresent() within thread freezes applet under Ubuntu
keang,
I followed your advice and put some Sleep in my loop.
I also re arranged a bit my code and put more displays to get a better idea of what's going on.
I now know what is causing this : the waitForCardPresent method throws the following Exception : javax.smartcardio.CardException: wait mismatch
at sun.security.smartcardio.TerminalImpl.waitForCard(TerminalImpl.java:103)
at sun.security.smartcardio.TerminalImpl.waitForCardPresent(TerminalImpl.java:116)
Apparently this exception is thrown when a card isn't present and the timeout as expired, but I set the timeout to 0 (TIMEOUT INFINITE). Replacing 0 with TIMEOUT_INFINITE (0xffffffff) doesn't work.
Re: waitForCardPresent() within thread freezes applet under Ubuntu
The relevant bit of code in the link you provided is
Code:
098 // no match, wait
099 status = SCardGetStatusChange(contextId, timeout, status, readers);
100 present = (status[0] & SCARD_STATE_PRESENT) != 0;
101 // should never happen
102 if (wantPresent != present) {
103 throw new CardException("wait mismatch");
Which interestingly has the comment "should never happen".
The code suggests the problem is in the call to SCardGetStatusChange(..). It's not timing out else it would throw a PCSCException so it must be returning an unexpected value. My guess is it is immediately returning a value without waiting for the timeout. You could try specifying a timeout value for instance 5 seconds and see if it actually waits before timing out - this will test to see if the problem is just with an indefinite wait.
The call is to a native method so it could be a bug in the native code which would explain why you don't see this problem on all platforms.
This is a bit of a bodge but you could try explicitly catching the CardException and waiting 'n' milliseconds before retrying. The problem is CardException can be thrown for other reasons so you will have to identify which CardException is being thrown before retrying. The other CardException that gets thrown will have a cause exception attached so you could use the fact that the exception you are getting doesn't have a cause and/or that it has the message "wait mismatch" to distinguish it (I did say this was a bodge). Additionally you may want to limit this retry mechanism to when you are running on the offending platform(s).
Re: waitForCardPresent() within thread freezes applet under Ubuntu
Keang,
Thank you for your reply.
I have tried putting a 5 seconds timeout (5000) :
- under Windows, it behaves the same as if I had put 0 (not the expected result, but not necessarily inconvenent there)
- under ubuntu, the Exception is thrown way before the 5 seconds, it's still the same exception.
I'm guessing as you said that the problem lies in the SCardGetStatusChange(..) function.
I should try to copy paste the code of this function (waitForCard) and add some displays to get a better idea of what's going on. The main problem on doing that would be to get the contextId.
Last edited by emilie.c@pro-active.fr; April 22nd, 2010 at 07:44 AM.
Otherwise, do you know who I could contact regarding this issue? Maybe Andreas Sterbenz, who is the author of those classes? I have googled him and found his blog, he says on his main page he's not working for Sun anymore, but maybe he could tell me who I could contact?
Bookmarks