Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

in windows, how to have non-blocking stdin that is a redirected pipe?

I have a Windows C program that gets its data through a redirected stdin pipe, sort of like this:

./some-data-generator | ./myprogram

The problem is that I need to be able to read from stdin in a non-blocking manner. The reason for this is that (1) the input is a data stream and there is no EOF and (2) the program needs to be able to abort its stdin-reading thread at any time. fread blocks when there's no data, so this makes it very difficult.

In Unix this is no problem, as you can set the blocking mode of a file descriptor with fcntl and O_NONBLOCK. However, fcntl doesn't exist on windows.

I tried using SetNamedPipeHandleState:

    DWORD mode= PIPE_READMODE_BYTE|PIPE_NOWAIT;
    BOOL ok= SetNamedPipeHandleState(GetStdHandle(STD_INPUT_HANDLE), &mode, NULL, NULL);
    DWORD err= GetLastError();

but this fails with ERROR_ACCESS_DENIED (0x5).

I'm not sure what else to do. Is this actually impossible (!) or is it just highly obfuscated? The resources on the net are rather sparse for this particular issue.

like image 521
paleozogt Avatar asked May 15 '09 18:05

paleozogt


2 Answers

The order apprach, check there is input ready to read:

  • For console mode, you can use GetNumberOfConsoleInputEvents().
  • For pipe redirection, you can use PeekNamedPipe()
like image 185
kcwu Avatar answered Nov 09 '22 14:11

kcwu


You could use async I/O to read from the handle, such as the ReadFileEx() WIN32 call. Use CancelIo() to terminate reading in the absence of input.

See MSDN at http://msdn.microsoft.com/en-us/library/aa365468(VS.85).aspx

like image 31
Conal Avatar answered Nov 09 '22 14:11

Conal