【发布时间】:2011-03-21 23:36:02
【问题描述】:
我正在将一些 Unix 代码移植到 Windows,它将 stderr 和 stdout 重定向到我创建的管道,并且有一个线程从该管道读取,然后将输出发送到调试控制台。这在 Unix 上运行良好,但我无法在 Windows 上运行。当管道的读取端关闭时会出现问题。它没有将 EOF 写入会导致线程退出的管道,而是死锁。为什么?
一种解决方法是跳过调用关闭,这让我有点担心,但由于我的过程是短暂的,也许这没什么大不了的?
这是说明问题的示例代码...我正在使用 VS 2010:
#include <cstdio>
#include <tchar.h>
#include <iostream>
#include <vector>
#include <fcntl.h>
#include <Windows.h>
#include <io.h>
#define posix_open _open
#define posix_read _read
#define posix_write _write
#define posix_pipe( fds ) _pipe( fds, 8096, _O_BINARY)
#define posix_close _close
#define posix_dup _dup
#define posix_dup2 _dup2
#define posix_fileno _fileno
using namespace std;
static const int PIPE_READ = 0;
static const int PIPE_WRITE = 1;
DWORD __stdcall PipeReaderFunc(void* readFd)
{
int pipeFd = *((int*)readFd);
vector< char > buffer(8096);
while( posix_read(pipeFd, &buffer[0], buffer.size() ) != 0 )
{
OutputDebugString( &buffer[0] );
}
return 0;
}
void test()
{
int pipefd[2] = {-1,-1};
if( posix_pipe( pipefd ) < 0 )
{ throw std::exception( "Failed to initialize pipe." );}
int stdoutOrig = posix_dup( _fileno(stdout) );
int stderrOrig = posix_dup( _fileno(stderr) );
if( -1 == posix_dup2( pipefd[PIPE_WRITE], posix_fileno(stdout) ) ) // closes stdout
{throw exception( "Failed to dup stdout fd." );}
if( -1 == posix_dup2( pipefd[PIPE_WRITE], posix_fileno(stderr) ) ) // closes stderr
{throw exception( "Failed to dup stderr fd." );}
HANDLE hThread = CreateThread( NULL, 0, PipeReaderFunc, &pipefd[PIPE_READ], 0, NULL);
if( NULL == hThread )
{throw exception("Failed to create thread");}
cout << "This should go to the debug console" << endl;
Sleep(1000); // Give time for the thread to read from the pipe
posix_close( stdoutOrig );
posix_close( stderrOrig );
posix_close( pipefd[PIPE_WRITE] );
// Deadlock occurs on this line
posix_close( pipefd[PIPE_READ] );
// This is commented out because it has no effect right now.
//WaitForSingleObject( hThread, INFINITE );
}
int _tmain(int argc, _TCHAR* argv[])
{
try
{ test(); }
catch( exception& ex )
{ cerr << ex.what() << endl; }
return 0;
}
感谢您提供有关如何解决此问题的任何想法!
【问题讨论】: