0

プロセス管理ライブラリにI/O完了ポートを使用しています(はい、これには理由があります)。ここで私が話していることのソースを見つけることができます:https ://github.com/jcommon/process/blob/master/src/main/java/jcommon/process/platform/win32/Win32ProcessLauncher.java (行559と1137を見てください-はい、そのクラスはリファクタリングしてクリーンアップする必要があります)。

子プロセスを起動し、子プロセスのstdoutとstderrを処理するために、名前付きパイプ(匿名パイプではなく、非同期のオーバーラップしたReadFile()/ WriteFile()が必要)を使用しています。これはほとんど実際に機能しています。テストでは、1,000の並行プロセスを起動し、それらの出力を監視して、適切な情報を出力することを確認します。通常、1,000個すべてが正常に機能するか、そのうち998個が正常に機能し、問題のあるカップルが残ります。

これらのいくつかのプロセスは、すべてのメッセージが受信されているわけではないことを示しています。メッセージが出力されていることはわかっていますが、そのプロセスのGetQueuedCompletionStatus()を処理しているスレッドは、ERROR_BROKEN_PIPEを使用して読み取りから戻ります。

予想される動作は、OS(またはC libs)が、プロセスの終了時にstdoutバッファー上の残りのバイトをフラッシュすることです。次に、パイプの破損エラーが発生する前に、これらのバイトがiocpのキューに入れられることを期待します。代わりに、これらのバイトは消えたように見え、読み取りはERROR_BROKEN_PIPEで完了します。これにより、私のコードでは、子プロセスのティアダウンが開始されます。

動作をテストして理解するための簡単なアプリケーションを作成しました(https://github.com/jcommon/process/blob/master/src/test/c/stdout-1.c)。このアプリケーションはstdoutのバッファリングを無効にするため、すべての書き込みをすぐに効果的にフラッシュする必要があります。テストでそのプログラムを使用すると、「cmd.exe /chechohi」を起動した場合と同じ問題が発生します。そしてとにかく、プロセスが終了するときに、アプリケーション(またはOS?)はstdoutの残りのバイトをフラッシュするべきではありませんか?

ソースはJavaであり、直接マップされたJNAを使用していますが、C /C++エンジニアにとってはかなり簡単に理解できるはずです。

あなたが提供できるどんな助けにも感謝します!

4

1 に答える 1