FreeRDP/FreeRDP — pull request #1885 by awakecoding (2014-06-04 16:33:44+00:00)
Title: SmartCard fixes and workarounds

Last attempt at resolving pcsc-lite deadlocks:

* Create a new SCARDCONTEXT for each SCARDHANDLE in pcsc-lite wrapper.

pcsc-lite lies when it says that SCARDCONTEXT is "thread safe". We already know that SCARDHANDLE in pcsc-lite is not thread safe (it is thread safe in WinSCard), so we are locking it accordingly. However, it doesn't make any sense that SCARDCONTEXT is thread safe in pcsc-lite as it corresponds directly to a single file descriptor used for communication with pcscd. Since there is no queuing of messages, different threads using the same SCARDCONTEXT will end up performing parallel read/read and write/write operations, which can only end up badly. The solution is to create a new SCARDCONTEXT under the hood for each SCARDHANDLE.

* Give up on pcsc-lite's broken transaction system

Transactions are used to lock other threads from performing certain operations on the same smartcard. So far, we have been calling pcsc-lite's SCardBeginTransaction/SCardEndTransaction when receiving those messages from the server. After wasting months chasing the reason *why* SCardConnect calls would eventually deadlock, we figured out that it was caused by some lock not being released properly in the pcscd daemon, a lock which is acquired with the transaction system. We have tried to find the bug without success, we also tried finding possible workarounds like limiting the number of transaction calls (transactions can be nested, some transactions may not be ended explicitly), without success as well. In the end, we never deadlock if we don't call pcsc-lite's transaction functions. Removing the safety belt may look like a big no-no, but since it works fine in most cases. Some failures may occur if you have multiple applications using the same smartcard at the same time, but that's much less frequent than the deadlocks that would *always* occur otherwise.

If the lack of transaction locking becomes a problem, one intermediate solution would be to attempt implementing the locking inside our pcsc-lite wrapper, which would lock fine within FreeRDP but wouldn't lock other local processes using the same smartcard.