この問題は多かれ少なかれ、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
)、dup
、dup2
などpipe
はerrno
引き続き「不正なシーク」に設定され、さらにチェックerrno
すると同じエラーが表示されます。
(実際には、実際のエラーはなかったので、すべてうまくいきました。また、errno
syscall とチェックの間に別のスレッドが 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
}
}
}
}