barlop barlop - 1 month ago 15
C# Question

My C# program gives an error "The process tried to write to a nonexistent pipe"

I am getting an error trying to write a program that displays the first 5 lines of a large file.

C:\blah\aeea2>for /L %f in (1,1,500) do @echo zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz >>testfile


That above generates my file. It's 500 lines with those z characters on each line.

C:\blah\aeea2>dir
Volume in drive C has no label.
Volume Serial Number is B411-D580

Directory of C:\blah\aeea2

16/10/2016 05:48 AM <DIR> .
16/10/2016 05:48 AM <DIR> ..
16/10/2016 05:42 AM 388 prog.csc
16/10/2016 05:42 AM 4,096 prog.exe
16/10/2016 05:48 AM 19,500 testfile
3 File(s) 23,984 bytes
2 Dir(s) 2,879,127,552 bytes free


You see my program here

C:\blah\aeea2>type prog.csc
class a{
public static void Main(string[] args) {
string line;
System.Collections.Generic.List<string> lststr = new System.Collections.Generic.List<string>();
int i=0;
while( (line=System.Console.In.ReadLine())!=null ) {i++; lststr.Add(line); if(i==5) break;}
for(i=0; i<lststr.Count; i++) System.Console.WriteLine(lststr[i]);
}
}


And here is the bug

C:\blah\aeea2>type testfile| prog.exe
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
The process tried to write to a nonexistent pipe.

C:\blah\aeea2>


But it works for a very small file

C:\blah\aeea2>type smallfile.txt
a
b
c
d
e
f
g
h
i
j
C:\blah\aeea2>type smallfile.txt| prog.exe
a
b
c
d
e

C:\blah\aeea2>

Answer

It's not your program, it's actually the type command.

type will try writing the full file content to the pipe and send it to your program. But your program consumes only first 5 lines and exits. Therefore type complains about no longer existing consumer (pipe).

In order to make it working without warnings/errors, it may be better to consume full input instead of breaking after i == 5 and just throw it out. However, it'll waste CPU and IO by reading something which is not needed.

The reason why it works for smaller files is that the remaining bytes fit into pipe buffer (usually 4kB, 8kB, not 100% sure on all Windows systems).

added by barlop

Some interesting findings involving the above, and the commands, gnuwin32 cat, cygwin cat, and the environments cmd, and cygwin, I found the following.

They all work (/ don't run into error), with zbynek's adjustment(making my program read the lot).

But without zbynek's adjustment -

The gnuwin32 cat command does not work from cmd, it behaves similarly to type and after outputting the lines, it says "write error: Invalid argument"

The cygwin cat command if done from cmd, does not work, it says "write error: No space left on device"

The windows 'more' command works from cmd(or unsurprisingly, from cygwin). So that can be used instead of 'type'.

And from cygwin, cat - either the gnuwin32 cat or the cygwin cat, work.

I would've tested 'type' from cygwin but I tried and I don't think cygwin can run type, it's built into the cmd.exe shell and doesn't have its own executable and I don't think cygwin can see it.