Carlos S. Na
Carlos S. Na

Reputation: 93

Named Pipes communication failure between a c# and C program

everyone. My team is currently developing a system that involves two parts: the data organization, UI, etc. in C#, and heavy number crunching in C due to performance requirements. We're trying to squeeze every little bit of performance so, while initially we were communicating both processes using files, we're moving on by communicating both processes through IPC. Specifically named pipes. A simplified version of the C# program that transfers the C program required data is this:

String pipeName = "some_random_name";
NamedPipeServerStream pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.Out, 2, PipeTransmissionMode.Byte, PipeOptions.None, 0, 4096);
Process someProcess= new Process();
someProcess.StartInfo.FileName = appDirectory + "someProcess.exe";
someProcess.StartInfo.RedirectStandardInput = true;
someProcess.StartInfo.RedirectStandardOutput = true;
someProcess.StartInfo.RedirectStandardError = false;
someProcess.StartInfo.UseShellExecute = false;

someProcess.StartInfo.Arguments = "\\\\.\\pipe\\" + pipeName;
someProcess.Start();
someProcess.PriorityClass = ProcessPriorityClass.RealTime;

pipeServer.WaitForConnection();
pipeServer.Write(BitConverter.GetBytes(lengthOfNextDataSent), 0, 4);
pipeServer.WaitForPipeDrain();

for (i = 0; i < lengthOfNextDataSent; i++){
    byte[] xBytes = BitConverter.GetBytes(SomeOtherIntegerData);
    pipeServer.Write(xBytes , 0, xBytes.Length);
}

While the simplified client C code is:

fd = open(argv[1], O_RDONLY);
read(fd, &received_length, sizeof(int));
for(i = 0; i < received_length; i++){
    read(fd, integer_array[i], 16);
}
close(fd);

The weird thing is, I'm able to correctly receive (in the C application) and decode up to 1820~ bytes. If I try to invoke the C# method WaitForPipeDrain or try to flush after after writing 1820~ bytes (in smaller blocks, either integer sized or bigger), a 'Pipe is broken' exception is thrown. If I try to write more bytes than that in one call, the C app crashes when reading.

Edit: A detail I forgot to mention. I'm compiling the C program with a cygwin-like environment (msys2 specifically) using the mingw32-64 compiler.

Can you tell me what am I doing wrong?

Upvotes: 2

Views: 191

Answers (1)

Ben Voigt
Ben Voigt

Reputation: 283614

You are ignoring the return value of the read call and assuming the entire buffer is valid.

On pipes, you must not ignore this.

There was just a discussion about this on Raymond Chen's blog: Changing the conditions under which ReadFile produces fewer bytes than requested, where it is discussed that under POSIX (which doesn't constrain Win32, strictly speaking, but does set the expectations that the Win32 API is careful to meet) your assumption is valid for ordinary local files, but not for pipes.

Upvotes: 2

Related Questions