I've developed a program that communicates with another program through anonymous pipes set up by the other program (not written by me).

The problem is that my program keeps crashing as soon as I add something more than just receiving the info. For example, if I add a simple "showMessage", it crashes, but works again if I remove it.

Here is the code:

procedure TArena.read_winboard; 
var text:string[50];
    ch:char;
begin
   while true do
   begin
      text:='';
      repeat
         read(input,ch);
         text:=text+ch;
      until ch=#10;

      //showMessage('this instruction makes the program crash');

      form1.memo1.Lines.Add(text);
 
   end;
end;

Obviously the showMessage-instruction is just an example. If I try to do any parsing of the incoming text (for example sending it to a parser-function of some sort), it crashes. But the code above, devoid of anything extra, doesn't crash, and I can tell by the ouput in the memo that everything is received as expected (and sending info the other way works as well). So the communication is working.

I hear that buffering handled wrongly can cause problems (even crashing?). Is the input used by that read function using a buffer? And is the read function I'm using a real systems call or a part of Delphi (internally doing the systems call)?

My program has no previous history of crashing.

Recommended Answers

All 8 Replies

Can you tell us the type of pipe and the operational modes of each end?

I suspect that you have got an unstable combination and/or buffer lag.

Can you tell us the type of pipe and the operational modes of each end?

I suspect that you have got an unstable combination and/or buffer lag.

I don't know much about the pipe since it's set up by the other program. All I do on my side is to get an output handle and create a new thread:

procedure TArena.openConnection; 
begin
   gHandleout:=getstdhandle(std_output_handle);
   createthread(nil,0,@TArena.read_winboard,nil,0,Threadid);
end;

This is what the creator of winboard (here referred to as xboard) says:

An xboard chess engine runs as a separate process from xboard itself, connected to xboard through a pair of anonymous pipes. The engine does not have to do anything special to set up these pipes. xboard sets up the pipes itself and starts the engine with one pipe as its standard input and the other as its standard output. The engine then reads commands from its standard input and writes responses to its standard output.

(link)

My problem pertains to Arena though, which is similar to Winboard but may be wired differently in regard to the pipes. Can't find any info specifically for Arena. I could ask, but I have a feeling that that knowledge shouldn't be necessary.

I got the connection code from this page. He claims the code is working and that he uses it himself.

One more thing, to answer my own questions:

Is the input used by that read function using a buffer? And is the read function I'm using a real systems call or a part of Delphi (internally doing the systems call)?

The read procedure doesn't use buffering, and it's a part of Delphi and not a systems call.

I'm not sure what is wrong. The read procedure should be using ReadFile behind the scenes. And an anonymous pipe doesn't have any significant caveats...

I think it is more likely that the new thread is crashing when you call ShowMessage. Typically you want to keep all GUI handling in the main thread. I haven't done much multi-threaded programming, and I don't remember all the details as to why this is so... but I think that's your problem and not the pipe.

Sorry I couldn't be of more help.

I think it is more likely that the new thread is crashing when you call ShowMessage. Typically you want to keep all GUI handling in the main thread. I haven't done much multi-threaded programming, and I don't remember all the details as to why this is so... but I think that's your problem and not the pipe.

Yes, I know for certain now that that's the case, as it works as it should (even the showMessage...) if I use the main thread to do the reading and parsing. I don't know if there is any drawback to doing it that way, but there shouldn't be since I don't use the GUI in these cases anyway (when the program essentially is a component to Arena).

Actually there is one drawback, and that's that I can't receive anything while my program 'thinks' (makes up a move, which could take time). I don't know how important it is to be able to receive in these cases. Of course the official recommendation is to always have it reading, but I'm not running av power plant and I don't think it's a big deal.

On the other hand, now that I know that some areas are "off limits" to the second thread, including GUI handling, I might be able to get that thread working.

Anyway, thanks for the help.

The pipe is like any other file/stream device. You can read at any time after the other end writes and you'll be OK.

Of course, for something like a plug-in for Arena you do want to minimize the time it takes to notice that there is input waiting to be read, but from your description it looks like that isn't a problem.

:)

Of course, for something like a plug-in for Arena you do want to minimize the time it takes to notice that there is input waiting to be read, but from your description it looks like that isn't a problem.

:)

It depends on the phase. When my program receives a move (it's a chess engine) there usually isn't any more input until it has replied, but thereafter it's important to notice input in order to receive new moves. Which it does. Also, there are some quick exanges done at the beginning of the game to set everything up, but at that point it's also alert with the reading.

Of course, it could it be the case that the opponent resigns, or the operator of Arena decides to cancel the ongoing game, or some such, and then my program won't know until it's finished thinking, and at that point the input may be lost. But that's an acceptable problem for the time being. Eventually I'll get that second thread going.

I did manage to connect them using the main thread, and my engine played through a couple of games against another engine. Fun and exiting to watch.

However, I now have another problem: How do I make it autostart reading when it's started by Arena (as against started as a standalone application). I do know how to recognize arena through its parameter, but that doesn't help. If I set it to start reading while in FormCreate, it crashes since FormCreate needs to be completed (I think). But if I let it complete how do I make the thread start reading where I want? Even if I set a flag during FormCreate to let it know it was started by Arena, how do make it check that flag? I can do it manually, through making an event happen, but it should be done automatically.

Start it in the DPR file between Application.CreateForm(...) and Application.Run.

? best guess...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.