1

I'm currently trying to create a simple program that writes and reads from/to the pipes of a process (cmd.exe), by calling CreateProcess().

I have 3 pipes:

  • Input
  • Output
  • Error

But reading from both output and error pipe is problematic.
I'm currently doing it like this:

while (readOutput) {
    DWORD bytesAvailable;

    PeekNamedPipe(OutputReadPipe, NULL, 0, NULL, &bytesAvailable, NULL);
    while (bytesAvailable > 0) {
        // Read the pipe and print the output
    }

    PeekNamedPipe(ErrorReadPipe, NULL, 0, NULL, &bytesAvailable, NULL);
    while (bytesAvailable > 0) {
        // Read the pipe and print the output
    }

    Sleep(20)
}

But sometimes cmd.exe writes to both pipes (error and output) at the same time and the reading order is incorrect, because I first read from the output pipe and then from the error pipe.

Is there a way I can read from both pipes in the correct order?

chrizator
  • 93
  • 1
  • 10
  • Consider using `poll()` or `select()` or variants thereupon. – Jonathan Leffler Jul 20 '18 at 15:49
  • @JonathanLeffler Unfortunately, I can't use said functions, since I'm compiling without C runtime library. WinAPI is all I have. – chrizator Jul 20 '18 at 16:08
  • If the program writes to both stdout and stderr "at the same time", how do you define "the correct order"? – rici Jul 20 '18 at 16:09
  • 2
    You probably need some combination of overlapped I/O and WaitForMultipleObjects so you can process each pipe as soon as it has data available to be read, rather than sleeping for 20 milliseconds in each loop iteration which mushes up the timings. – Ian Abbott Jul 20 '18 at 16:14
  • @rici I probably didn't express myself right. Obviously, the writes don't occur at the same time, but in a very small time span. So small, that they both occur while I `Sleep()` 20ms – chrizator Jul 20 '18 at 16:14
  • @IanAbbott Never heard of overlapped I/O. I just read about it on MSDN and it sounds promising. Appreciate it! – chrizator Jul 20 '18 at 16:16
  • 2
    chrizator: I get what you mean, but I think it's based on a fallacy. Pipes are not synchronized with each other and there is a delay between data entering one end of a pipe and emerging from the other end. So if a process writes X to pipe A and then writes Y to pipe B, *nothing* guarantees that another process will see that pipe A has available data before pipe B does. It is entirely possible that Y emerges emerges first, because some combination of implementation factors result in a higher delay in A at this moment. So I'd argue that there is no such thing as "the correct order"... – rici Jul 20 '18 at 16:21
  • Overlapped I/O cannot be used on anonymous pipes though, so it might not help. – Ian Abbott Jul 20 '18 at 16:22
  • Nonetheless, using an OS facility to inform you when data is available is a better solution than trying in a loop. – rici Jul 20 '18 at 16:22
  • 2
    However, pseudo anonymous pipes (named pipes with generated, "temporary" names) could be used, as in [this answer](https://stackoverflow.com/a/419736/5264491). – Ian Abbott Jul 20 '18 at 16:27
  • @IanAbbott - really asynchronous(overlapped) io can be used as well on any pipes. this is simply `CreatePipe` bad design, which not let specify asynchronous io type for created pipe. – RbMm Jul 20 '18 at 16:38
  • If you don't need to separate error output from normal output, just use same handle for `STD_OUTPUT_HANDLE` and `STD_ERROR_HANDLE`. – Daniel Sęk Jul 21 '18 at 06:07
  • @RbMm Yes, it seems to be bad design because even `CreatePipe` creates anonymous pipes using named pipes. You'd have thought Microsoft would have added a `CreatePipeEx` function to allow overlapped I/O by now! – Ian Abbott Jul 23 '18 at 14:40
  • @IanAbbott - not exist different pipe types. exist only single one. what name of the pipe (empty as particular case) nothing change in pipe properties. and `CreatePipe` creates "anonymous" pipes using special format name before win7 only begin win 7 it create pipe pair with empty name. but confuse say about named or anonymous pipes, like this is 2 different object types. this is false. how i say exist only pipes. – RbMm Jul 23 '18 at 15:14

0 Answers0