我将一些Unix代码移植到Windows,它将stderr和stdout重定向到我创建的管道,并且有一个线程从此管道读取,然后将输出发送到调试控制台。这在Unix上运行良好,但我无法在Windows上运行。当管道的读取面关闭时出现问题。它不会将EOF写入会导致线程退出的管道,而是死锁。为什么?关闭管道时发生死锁fd
一种解决方法是跳过电话关闭,这让我很担心,但由于我的过程很短暂,也许这不是什么大不了的事?
下面是示例代码说明了这个问题......我使用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;
}
感谢如何解决这个任何想法!
啊是的,这是正确的。在Unix上,当管道的读取结束时关闭EOF。在Windows上,你不会得到EOF,直到引用管道的所有fds都关闭,并且我没有关闭它们。现在完美。谢谢! – Skrymsli 2011-03-22 16:32:10