0
votes

I'm trying to write a Pascal (Lazarus/FPC) program that is started by another program as a process. The caller (the Arena chess GUI) talks to my program using StdIn and StdOut.

First I used READLN in my program to get the text commands sent from the GUI and WRITELN to reply to them. That worked well except that my program would stop doing anything if the READLN had to wait for input from the GUI. Since I wanted the program to carry on working and only deal with commands as they arrived I had to change this.

So I changed the code to use:

...
var   inpStream        : TInputPipeStream;
...
inpStream := TInputPipeStream.Create(StdInputHandle);
...
if inpStream.NumBytesAvailable > 0 then begin
    SetLength(s_buffer, inpStream.NumBytesAvailable);
    inpStream.Read(s_buffer[1], length(s_buffer));
end;
...

That worked really well as it no longer paused for the read. But then the WRITELN stopped working: nothing gets sent back to the GUI. I thought maybe this would help:

...
var inpStream        : TInputPipeStream;
    outStream        : TOutputPipeStream;
...
inpStream := TInputPipeStream.Create(StdInputHandle);
outStream := TOutputPipeStream.Create(StdOutputHandle);
...
if inpStream.NumBytesAvailable > 0 then begin
    SetLength(s_buffer, inpStream.NumBytesAvailable);
    inpStream.Read(s_buffer[1], length(s_buffer));
end;
...
outStream.Write(s_buffer, length(s_buffer));

But that makes it worse as now it doesn't read or write anything. So how can I have non-blocked input on StdIn while maintaining the ability to write to StdOut?

2

2 Answers

0
votes

Assuming you use Windows, probably that means that the program that reads your output doesn't read it often enough (it lets it mass up), and then when the total size of pipes reaches a certain size (typically several MBs) windows stops processing.

This is a new situation that would require digging deeping into Windows pipes and job control. In FPC 3.x TProcess some bugs were fixed, and they were similar (pipe processing stalled if stderr wasn't regularly processed too, see the intruncommand code).

If the receiving program doesn't process stderr, don't use it.

0
votes

Well, this is embarrassing! Turns out the replies to the GUI weren't being sent properly due to a logic error in my program. Thanks for your answer though Marco, and yes I am using Windows. So it turns out that:

READLN/WRITELN works but stops the program until an entry is made to the READLN.

TInputPipeStream/WRITELN works without stopping the program so is the solution to my problem.

TInputStream/TOutputStream don't seem to work together and I'm not sure why. Is it the way I'm trying to initialise them or are they supposed to be exclusive?