私は、GNU/Linux、MacOS、Windows上でさまざまなpcsc
の実装を使用してカードリーダーに接続するQtアプリケーションを持っています。カードとのすべての通信はワーカースレッドで実行されます。pcscコールを実行しているQThreadのブロックを解除するには?
ユーザは、カードリーダを介してカードとの通信を必要とする動作を開始する。カードリーダにはキーボードがあり、認証手続き中にユーザはPINをリーダーのキーボードに入力する必要があります。
この操作は、SCardControl()
(例:the Microsoft documentationを参照)を呼び出すことによって実装されます。ユーザーがリーダーで作業している間は、SCardControl()
への呼び出しは終了せず、ワーカースレッドはそのスレッドによってブロックされます。
この時点で、ユーザーは操作が保留中の間にアプリケーションを閉じることを決定することがあります。ワーカースレッドがSCardControl()
が戻るのを待ってブロックされている
- :ので、この時点でアプリケーションを閉じると、(信号
SIGABRT
でLinux上)がクラッシュするアプリケーションが発生します。 - メインスレッドはブロックされたスレッドを停止できません。
quit()
もterminate()
もスレッドを終了させません。 - アプリケーションが終了すると、ワーカースレッドのオブジェクト
QThread
が破棄され、スレッドはまだ実行状態であるため、エラーを示す信号がスローされます。
私はいくつかの解決策を試しました。
- サブクラス
QThread
とQThread::terminate()
て終了を許可するようにsetTerminationEnabled(true);
を呼び出すワーカースレッドを作成します。これはMacOS
では機能しません。QThread
が破棄された場合、スレッドはまだ実行状態にあり、信号SIGABRT
が発行されます。 - シャットダウン時にハンドルシグナル
SIGABRT
を処理し、無視します。これはいい考えではありませんでしたが、私はそれを捨てる前に試してみたかったのです。信号SIGABRT
を無視した後、信号SIGSEGV
が受信され、アプリケーションがクラッシュします。私はhereと記載された手法を採用しました。 - メインスレッドからカードリーダーにコマンドを送信してスレッドのブロックを解除してください。私は
SCardCancel()
とSCardDisconnect()
とSCardReleaseContext()
を試しましたが、これらのコマンドはブロックされたスレッドに影響を与えませんでした。
一部の関数呼び出しでスレッドがブロックされても、アプリケーションを完全にシャットダウンすることはできないが、私が試したすべての解決策は機能しておらず、アイデアが足りなくなっている。私は何か見落としましたか?誰も便利なヒントを持っていますか?
EDIT
私はQThread
のためのQtのソースコードに見て、Unixライクなプラットフォーム上でQThread::terminate()
が内部pthread_cancel()
を使用していることが分かりました。しかし、明らかにpthread_cancel()
は動作しません/ Darwin
に何もしません。 hereおよびhere。
だから、実際には、読者からカードを削除するように求めるダイアログをユーザに表示するオプションを選択する必要があります。
"通話中にブロックされていると、外部からスレッドをきれいにシャットダウンすることはできません。":スレッドがアプリケーション全体をハイジャックする可能性があるのは非常に驚きです。 –