2014 年 1 月 9 日更新: TL;DR バージョン: Cygwin で Cygwin 以外のプログラムを呼び出せるようにする方法については、この投稿の最後に移動してください。
かなりのサイズの bash スクリプトを作成するのに時間を費やした後、Cygwin の新しいバージョンではそれらが壊れています。これらのスクリプトは、Cygwin とリンクしていないネイティブの Win32 アプリケーションを呼び出します。これは明らかに Cygwin によって公式にサポートされていません。
Cygwin は、Cygwin 以外のネイティブ Win32 アプリと、Cygwin 互換レイヤーを使用する POSIX プログラムの両方を組み合わせた、より混合された環境で使用できるという印象を長年受けていたので、これは私にとって驚きでした。しかし、実際にサポートされているのは明らかに POSIX 互換レイヤーだけであり、ネイティブの Win32 非 Cygwin アプリが機能する場合、それは幸運な偶然と見なされます。
これは、Cygwin 内から .NET Framework に対してコンパイルされたプログラムを実行する際に遭遇した非互換性からわかりました。これは以前は正常に機能していましたが、数か月前に壊れました。特に、他の Win32 プログラムの標準入力にパイプされた .NET プログラムからの標準出力は、通常、受信側の Win32 プログラムが時期尚早のファイル終了シグナルを取得する原因となります。これは、Cygwin が数か月前に最近バイト パイプからメッセージ パイプに切り替えたためです。 - メッセージ パイプは、Visual C++ または .NET Framework を使用する受信アプリと互換性がないようです。これは、.NET が標準出力に null 書き込みを発行し、メッセージ パイプが使用されている場合にのみ受信アプリに渡されるためです。受信アプリはゼロバイトを正常に読み取るため、ファイルの終わりであると考えます。プロジェクト リーダーは「
メーリング リストの複数の電子メールからプロジェクト リーダーの Christopher Faylor を引用するには:
表示されているのは、Cygwin が数回前にメッセージ タイプのパイプを使用するように変更されたことが原因である可能性があります。これは変わりません。この変更は、Cygwin プログラムの問題を修正するために採用されたものであり、明らかに私たちの最優先事項です。
Visual C++ や .NET を使用しているユーザーの数に関係なく、彼らは私たちのターゲット ユーザーではありません。UNIX ツールを使いたくないが、私たちの主な焦点ではない人々のために物事が機能するのは素晴らしいことです。Cygwin 以外のものを使用したい人のために問題を修正することは、私が優先度が高いとは思いません。
pipe.cc から: パイプの書き込み側が PIPE_TYPE_MESSAGE として開かれていることに注意してください。これはLinux パイプの動作をより厳密に模倣しているようであり、fhandler_pty_master がチャンクでパイプに書き込み、CANON モードが指定されている場合は改行で終了するため、pty 処理には間違いなく必要です。
上記のコメントは、ここで「and」関係を示しています。メッセージ タイプ パイプは、Linux (UNIX) パイプの動作をより厳密に模倣し、pty には確実に必要です。
ランタイムにはおそらくバグがあるという James の意見に同意しますが、cygwin がこれらのシナリオを処理できるはずであるという点にも同意します。
お互いに完全に合意しても、あまり効果はありません。投票によって Cygwin のソース コードが変更されることはありません。
この 1 つの問題が最終的になんらかの形で修正されたとしても (誰にもわかりませんが)、彼らは 3 か月以内に別の何かを壊す可能性があり、リグレッションを修正する気はありません。彼らはパッチを検討するかもしれませんが、機能するものを見つけるにはかなりの時間がかかります. 彼らがネイティブの Win32 アプリとの互換性を壊すことをいとわないことは明らかであり、Win32 アプリを動作させるためにこれ以上時間を無駄にしたくないことは明らかなので、他の場所で時間を費やしたほうがよいと思います。したがって、Cygwin は、Win32/Cygwin が混在する環境の安定したプラットフォームと見なされるべきではないと思います - 私の代替手段は何ですか? bash以外のものへの完全な書き直しを避けるには、どこから始めればよいでしょうか? Cygwin の基本インストール + いくつかの基本的な perl スクリプト以外は使用しません。
更新: この元の質問を投稿した後、彼らは最終的に環境変数に新しいpipe_byte
フラグを追加しましたCYGWIN
: ドキュメントを見てください。このフラグが設定されている場合、上記の問題が修正されます。Cygwin 以外の Win32 プログラムを呼び出すときは、常にpipe_byte
フラグが設定されていることを確認してください。
しかし、その後、.NET Framework 4.0 および Cygwin との非互換性が明らかになりました。以前のバージョンの .NET Framework には、この問題はありません。この問題については、Cygwin のメーリング リストで最初に言及しました。
Cygwin と .NET Framework 4.0 間のパイプ同期と非互換性
実りある応答が得られなかったので、さらに調査したところ、Cygwin が重複したパイプを作成しており、それが問題の原因であることがわかりました。オーバーラップされたパイプでオーバーラップされていない Win32 API 呼び出しを使用しようとすることは未定義であり、ほとんど (すべて?) の Win32 非 Cygwin プログラムは、標準のファイル ハンドルでオーバーラップされた I/O を使用しないことに注意してください。これが起こらないようにするpipe_nooverlap
フラグを環境変数に作成するパッチを提出しました。CYGWIN
残念ながら、彼らはパッチを拒否したため、メインの Cygwin DLL にこれが表示されることはありません。
Re: オーバーラップしたパイプをオプションで無効にするパッチ
パッチを拒否する理由:
- Cygwin でのシグナルの実装を壊したことが暗示されていました。信号はまだ重複したパイプを使用しているため、これが当てはまるとは思いませんでした。
- 明らかに問題を修正しているにもかかわらず、環境変数フラグを追加する気はありません。
- 彼らは、重複しないパイプを持つオプションさえあるコードをサポートしたくありません。
このような推論と態度では、彼らの要件に合うようにパッチを変更する方法を思いつかないのではないかと心配しています. パッチをしばらく使用していますが、問題はありません。また、フラグが壊れる状況は考えられませんがpipe_nooverlap
(彼らのメーリング リストでフォローアップの電子メールを参照してください)、問題が発生した場合に備えてフラグとして残しました。
そのため、Cygwin から Cygwin 以外の Win32 または .NET Framework プログラムを呼び出したい場合は、次の手順を実行する必要があります。
- 使用している Cygwin バージョンのソースに私のパッチを適用してください。このパッチが将来の Cygwin バージョンに表示されるとは思わないでください。
- 環境変数に
pipe_byte
およびpipe_nooverlap
フラグを設定します。CYGWIN
これはうまくいきます...今のところ!!! Cygwin を何かに使いたいと思っている他の人に役立つ場合に備えて、これを投稿します。