1

I 'm using the CreatePipe to redirect stdin/out from a process to my process.

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

This works ok so far. The problem is when I want to terminate the thread that waits for the client process to write something.

I can use CancelIoEx() but this only works in Vista+, and I also want an XP solution. Without CancelIoEx(), ReadFile() in the other thread never returns.

I cannot also use OVERLAPPED ReadFile, for pipes created with CreatePipe do not support it.

Any options?

Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78

1 Answers1

0

Save a handle to the write end of the stdout pipe when creating the child process. You can then write a character to this to unblock the thread that has called ReadFile (that is reading from the read end of the stdout pipe). In order not to interpret this as data, create an Event (CreateEvent) that is set (SetEvent) in the thread that writes the dummy character, and is checked after ReadFile returns. A bit messy, but seems to work.

/* 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);
}
srce
  • 45
  • 5