php エディタ Apple は、Go で書かれた Python 拡張機能が Ctrl C 信号を処理するときに問題が発生する可能性があることを発見しました。通常、コマンド ラインで Ctrl C を押すと、実行中のプログラムに SIGINT シグナルが送信され、実行の停止を要求します。ただし、Go で作成された Python 拡張機能はこのシグナルを無視するようで、プログラムが正常に停止できません。この問題は、Go を使用して Python 拡張機能を作成する開発者にとって潜在的な潜在的な危険であり、特別な注意が必要です。したがって、開発プロセス中に、プログラムが正常に終了するように、この問題を解決する解決策を探す必要があります。
サービスに接続して何らかの処理を行うgoで書かれたPythonドライバーを使用しています。サービスの「異常な」インスタンスに関する問題が発見されました。これにより、ドライバーがスタックし、プロセスを kill
しない限り終了できなくなります。
いくつかの実験を行ったところ、go で書かれた拡張機能を実行すると、プログラムは制御が Python に戻るまで発行された ctrl c
コマンドを無視しますが、c で書かれた拡張機能ではこのようなことは起こりません。これは、C コードの実行中に keyboardinterrupt
がスローされた場合です。私の 質問は、なぜこのようなことが起こっているのか と、これを回避する方法や、何らかの タイムアウト を発行する方法はあるのかということです。 threading.timer
を使用して例外を発生させてタイムアウトをシミュレートしようとしましたが、問題は例外が独自のスレッドで発生し、メインスレッドを中断しないことです。 Python (cpython) 3.9
および 3.10
でテストされました。私が作成した POC 拡張機能については、go バージョンは 1.20.4
、c コンパイラは 9.4.0
です。
以下に小さなポックを残しておきます。
Pythonコード:
リーリーgo 拡張機能
リーリーc拡張子
import ctypes import ctypes go_library = ctypes.cdll.loadlibrary('./go_library.so') hello_go = go_library.helloworld c_library = ctypes.cdll.loadlibrary("./c_library.so") hello_c = c_library.helloworld try: print("calling golang code") hello_go() print("calling c code") hello_c() except keyboardinterrupt: print("ctrl+c issued dd:") finally: print("done")
私も同じ状況に遭遇しました。いくつか調べた結果、解決策が見つかりました。
この回答に基づく :
Python は、メインのインタープリター ループによってチェックされるフラグを設定するだけのシグナル ハンドラーを signint にインストールします。このハンドラーが適切に動作するには、Python インタープリターが Python コードを実行する必要があります。golang コードを実行すると、golang は Python によってインストールされた sigint シグナル ハンドラーを呼び出してフラグを設定するようです。したがって、Python に戻って実行すると、キーボード割り込みが検出されます。
golang ドキュメントより :
(非 go プログラムが go コードを呼び出す場合) 非同期シグナルに対して Notice が呼び出された場合、そのシグナルに対して go シグナル ハンドラーがインストールされます。後でシグナルに対してリセットが呼び出された場合、シグナルの元の処理が再インストールされ、非 go シグナル ハンドラー (存在する場合) が復元されます。したがって、以下のコードは go コードで sigint をキャプチャし、sigint ですぐに関数を返します。
リーリー
以上がGo で書かれた Python 拡張機能は Ctrl+C を無視しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。