santigimeno / node-pcsclite

Bindings over pcsclite to access Smart Cards
ISC License
170 stars 127 forks source link

How to shut down an application cleanly? #70

Open martinpaljak opened 7 years ago

martinpaljak commented 7 years ago

I am a bit confused about cleanly closing the runtime after I am done with the reader I am interested in.

There is reader.disconnect() which is a wrapper around SCardDisconnect(), thus I obviously call it.

Then there is reader.close() which is intended to call SCardCancel() (for this specific reader?). I call it and get no errors.

Then there is pcsc.close() which is intended to also call SCardCancel() (for PnP reader tracking?). I call it and get an error event on pcsc: SCardGetStatusChange error: Command cancelled.(0x80100002). And the node process does not exit after this call. AFAIU SCardGetStatusChange should never emit an error if it is cancelled (I suspect this is a bug)

Two questions:

santigimeno commented 7 years ago

@martinpaljak thanks for the detailed report.

WRT pcsc.close(), reader.close(), it's not just about calling SCardCancel() but also cleaning up the threads where SCardGetStatusChange() run. If the program doesn't exit it's probably due to a deadlock. Can you post code that reproduces the error? (platform/reader/ etc)

Why are there two status checkers? AFAIU one call for SCardGetStatusChange should be sufficient, also for getting events for the pnp pseudo-reader as well as any connected readers, to be able to emit reade events (thus a pcsc.close() should be sufficient, and should result in normal exit of nodejs runtime?)

You're right. This could be done with only one SCardGetStatusChange(). It's been on my radar for a while but haven't had time yet. Would you be up for it :) ?

martinpaljak commented 7 years ago

I tried to read and fix some, but got lost in the code and how threads are handled with libuv (?) and ... I might come back to this at some later time or with #71 , right now process.exit() is OK for me.

dimdimdimdim commented 5 years ago

@martinpaljak This can easily be avoided if you simply set an error listener on the main pcsc object. I ran into the same problem (SCardCancel error notification on pcsc.close(), which is indeed unexpected), and I noticed that this output is done from the node EventEmitter code, which treats "error" events as a special case and prints the message when there is no listener.

So, as an easy fix, just set an empty listener:

pcsc.on('error', function(err) {
});

Or, if you want to handle the errors from the listener but only ignore the SCardCancel case, set a flag before doing pcsc.close() and, in your listener, ignore any error that may arise after set flag is set.