2014-11-23 1 views
0

CreatePipe를 사용하여 프로세스에서 프로세스로 stdin/out을 리디렉션합니다.파이프에 대한 IO 취소

http://msdn.microsoft.com/en-us/library/windows/desktop/aa365152(v=vs.85).aspx

이 지금까지 확인을 작동합니다. 문제는 클라이언트 프로세스가 뭔가 쓸 것을 기다리는 스레드를 종료하려고 할 때입니다.

CancelIoEx()를 사용할 수 있지만 Vista +에서만 작동하며 XP 솔루션도 필요합니다. CancelIoEx()가 없으면 다른 스레드의 ReadFile()이 반환되지 않습니다.

CreatePipe로 만든 파이프를 지원하지 않으면 OVERLAPPED ReadFile을 사용할 수 없습니다.

옵션이 있습니까?

+0

파이프를 닫으면 ReadFile()이 실패합니다. –

+0

@HansPassant, CloseHandle() 블록은 그렇지 않습니다. – Michael

+0

대신 CreateNamedPipe를 사용하면 겹쳐진 I/O를 사용할 수 있습니다. –

답변

0

자식 프로세스를 생성 할 때 stdout 파이프의 쓰기 엔드에 핸들을 저장하십시오. 그런 다음 문자를 써서 ReadFile (stdout 파이프의 읽기 끝에서 읽음)을 호출 한 스레드의 차단을 해제 할 수 있습니다. 이것을 데이터로 해석하지 않으려면 더미 문자를 쓰는 스레드에서 SetEvent (SetEvent) 이벤트를 만들고 ReadFile이 반환 된 후에 확인합니다. 약간 지저분하지만 작동하는 것 같습니다.

/* Init */ 

stdout_closed_event = CreateEvent(NULL, TRUE, FALSE, NULL); 

/* Read thread */ 

read_result = ReadFile(stdout_read, data, buf_len, &bytes_read, NULL);    
if (!read_result) 
    ret = -1; 
else 
    ret = bytes_read;  
if ((bytes_read > 0) && (WAIT_OBJECT_0 == WaitForSingleObject(stdout_closed_event, 0))) { 
    if (data[bytes_read-1] == eot) { 
     if (bytes_read > 1) {      
      /* Discard eot character, but return the rest of the read data that should be valid. */  
      ret--; 
     } else { 
      /* No data. */ 
      ret = -1; 
     } 
    } 
} 

/* Cancel thread */ 

HMODULE mod = LoadLibrary (L"Kernel32.dll"); 
BOOL WINAPI (*cancel_io_ex) (HANDLE, LPOVERLAPPED) = NULL; 
if (mod != NULL) { 
    cancel_io_ex = (BOOL WINAPI (*) (HANDLE, LPOVERLAPPED)) GetProcAddress (mod, "CancelIoEx");   
} 
if (cancel_io_ex != NULL) { 
    cancel_io_ex(stdout_write_pipe, NULL); 
} else { 
    SetEvent(stdout_closed_event);    
    WriteFile(stdout_write_pipe, &eot, 1, &written, NULL); 
} 
관련 문제