2

この問題は多かれ少なかれ、C に埋め込まれた perl、perlapio、つまりWindows 環境で解決したと思うSTDIO との相互運用性に関連しています。この新しい問題も解決された場合は、完全な解決策を投稿します。

リンクされた質問で、 StoryTeller は当面の問題を解決する ためのヒントをくれましたが、Linux で同じコードが奇妙に動作します。PerlIO_findFILE()

Perldup2()は Win32 では異なる動作をしているようです。ここで、dup2()は のマクロでwin32_dup2()あり、私が理解している限り、単にdup2()fromを使用していio.hます。

Win32 では、Perl のバージョンは成功時にゼロを返し、エラー時に非ゼロを返しますが、Linux ではデフォルトの ANSIdup2()が使用され、代わりに新しいファイル記述子が返されます。次に、errnoすべてがうまくいったかどうかを確認する必要があります。

への呼び出しが「不正なシーク」にPerlIO_findFILE()設定errnoされている場合 (errno 29 - ESPIPE)、dupdup2などpipeerrno引き続き「不正なシーク」に設定され、さらにチェックerrnoすると同じエラーが表示されます。

(実際には、実際のエラーはなかったので、すべてうまくいきました。また、errnosyscall とチェックの間に別のスレッドが errno をリセットする可能性があるため、チェックによる解決策はスレッドセーフではありません。)

私が持っていることに注意してください

#define PERLIO_NOT_STDIO 0

事実上、私はPerl5.14.1を使用しています。

私はここで本当に間違ったことをしていますか?

簡単なコード スニペットを次に示します。

stdOutFILE = PerlIO_findFILE(PerlIO_stderr()); // convert Perl's stdout to stdio FILE handle

fdStdOutOriginal = fileno(stdOutFILE);         // get descriptor

if ( fdStdOutOriginal >= 0 ) {

    relocatedStdOut = dup(fdStdOutOriginal);   // relocate stdOut for external writing

    if ( relocatedStdOut >= 0 )
    {
        if ( pipe(fdPipeStdOut) == 0 )         // create pipe for forwarding to stderr
        {
            // this has to be done on win32:
            // if ( dup2(fdPipeStdOut[1], fdStdOutOriginal)  == 0 ) // hang pipe on stdOut

            dup2(fdPipeStdOut[1], fdStdOutOriginal);

            if( errno == 0 ) {
                // do some funny stuff
            } else {
                // report error
            }
        }
    }
}
4

1 に答える 1