From: Andrew Wagner Date: 2013-03-16T10:33:47+09:00 Subject: Re: IO buffering problem --20cf307c9fc026b3ae04d800bf40 Content-Type: text/plain; charset=UTF-8 Yep, I think you're dead-on right. Thanks again. On Fri, Mar 15, 2013 at 8:23 PM, Garthy D < garthy_lmkltybr@entropicsoftware.com> wrote: > > Hi Andrew, > > Happy to be able to help, even if only indirectly. :) > > Also check out "trap" ("Signal.trap") if you can usefully catch and use > those SIGINTs. Perhaps they're tied to certain commands like "force" in the > protocol in case you need to stop "thinking" on a move? That's a wild guess > based on a two-minute reading of the protocol though. > > Cheers, > Garth > > > On 16/03/13 11:46, Andrew Wagner wrote: > >> Ha, I fixed it. You were almost right, Garthy, the UI was >> seemingly-randomly sending me SIGINTs. I had to tell it in the protocol >> initializer not to do that. Very odd. >> >> >> On Fri, Mar 15, 2013 at 8:09 PM, Andrew Wagner > >> wrote: >> >> Thanks for the response. I really don't have to handle every >> incoming response. I put in the line you suggested, and it did >> indeed identify a number of commands that are "unknown". But that's >> ok, as far as I can tell. >> >> As for "if" vs. "case", in my real program, I did something even >> more general: >> https://github.com/arwagner/**tdchess/blob/master/lib/** >> tdchess/runner.rb. >> This lets you plug in any command handlers you want. I plan on >> having a library of handlers for different commands, maybe a nice >> DSL or something for creating new ones, etc. Obviously, I shortened >> all of that to isolate this problem. >> >> >> On Fri, Mar 15, 2013 at 7:57 PM, Garthy D >> >> >> >> wrote: >> >> Hi Andrew, >> >> >> On 16/03/13 09:04, Andrew Wagner wrote: >> >> All, >> I'm writing a chess program that has a simple text-based >> interface. It's >> designed to be run by another program, which has a nice UI. >> Here's the >> program as it stands now, whittled to the simplest possible >> use case: >> >> i = 0 >> moves = ["a7a6","a6a5","a5a4","a4a3"] >> $stdin.each do |command| >> if command.start_with?("protover"**__) >> >> $stdout.puts "feature ping=0 setboard=1 ics=1 >> usermove=1" >> elsif command.start_with?("usermove"**__) >> >> $stdout.puts "move #{moves[i]}" >> i+=1 >> end >> $stdout.flush >> end >> >> The "protover" thing is needed to tell the UI program how to >> initialize >> the protocol, and then every time a move is made, the UI >> program sends >> "usermove " to my program, which responds with >> "move ". >> >> If I run this by itself, I can happily enter a few >> 'usermove' commands >> manually, and get any number of canned moves back. However, >> when I run >> this under the UI, I get an Interrupt: >> >> bin/winboard.rb:3:in `each': Interrupt >> from bin/winboard.rb:3:in `
' >> >> I know that the UI program is pretty reliable, so I'm >> missing something >> in the way that I'm handling IO buffering or something. If >> you want the >> nitty gritty details, you can see them at >> http://www.gnu.org/software/__**xboard/engine-intf.html >> >> > >> . I'm >> running on >> MacOSX. Any suggestions? >> >> >> Is it possible that you aren't processing one of the commands >> from the program, and the program is terminating your script, >> perhaps after a timeout or incorrect response? I'm wondering >> what would show up if you added this: >> >> else >> $stderr.print "Unknown command: '#{command}'\n" >> >> just before the second-last line. Are you handling every >> incoming command as it expects? >> >> Incidentally, you could always turn those if statements into >> case/when, something like: >> >> case command >> when /^protover/ >> ... >> when /^usermove/ >> ... >> else >> $stderr.print "Unknown command: '#{command}'\n" >> end >> >> This might make it easier if there are a lot of commands you >> need to respond to. >> >> Cheers, >> Garth >> >> >> >> > > --20cf307c9fc026b3ae04d800bf40 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Yep, I think you're dead-on right. Thanks again.


On Fri, Mar 15, 201= 3 at 8:23 PM, Garthy D <garthy_lmkltybr@entropicsoftwar= e.com> wrote:

Hi Andrew,

Happy to be able to help, even if only indirectly. :)

Also check out "trap" ("Signal.trap") if you can useful= ly catch and use those SIGINTs. Perhaps they're tied to certain command= s like "force" in the protocol in case you need to stop "thi= nking" on a move? That's a wild guess based on a two-minute readin= g of the protocol though.

Cheers,
Garth


On 16/03/13 11:46, Andrew Wagner wrote:
Ha, I fixed it. You were almost right, Garthy, the UI was
seemingly-randomly sending me SIGINTs. I had to tell it in the protocol
initializer not to do that. Very odd.


On Fri, Mar 15, 2013 at 8:09 PM, Andrew Wagner <wagner.andrew@gmail.com
<= div> <mailto:wag= ner.andrew@gmail.com>> wrote:

=C2=A0 =C2=A0 Thanks for the response. I really don't have to handle ev= ery
=C2=A0 =C2=A0 incoming response. I put in the line you suggested, and it di= d
=C2=A0 =C2=A0 indeed identify a number of commands that are "unknown&q= uot;. But that's
=C2=A0 =C2=A0 ok, as far as I can tell.

=C2=A0 =C2=A0 As for "if" vs. "case", in my real progra= m, I did something even
=C2=A0 =C2=A0 more general:
=C2=A0 =C2=A0 https://github.com/arwagner/t= dchess/blob/master/lib/tdchess/runner.rb .
=C2=A0 =C2=A0 This lets you plug in any command handlers you want. I plan o= n
=C2=A0 =C2=A0 having a library of handlers for different commands, maybe a = nice
=C2=A0 =C2=A0 DSL or something for creating new ones, etc. Obviously, I sho= rtened
=C2=A0 =C2=A0 all of that to isolate this problem.


=C2=A0 =C2=A0 On Fri, Mar 15, 2013 at 7:57 PM, Garthy D
=C2=A0 =C2=A0 <garthy_lmkltybr@entropicsoftware.com
<= div> =C2=A0 =C2=A0 <mailto:garthy_lmkltybr@entropicsoftware.com>= > wrote:

=C2=A0 =C2=A0 =C2=A0 =C2=A0 Hi Andrew,


=C2=A0 =C2=A0 =C2=A0 =C2=A0 On 16/03/13 09:04, Andrew Wagner wrote:

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 All,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 I'm writing a chess program t= hat has a simple text-based
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 interface. It's
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 designed to be run by another pro= gram, which has a nice UI.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Here's the
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 program as it stands now, whittle= d to the simplest possible
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 use case:

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 i =3D 0
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 moves =3D ["a7a6","= ;a6a5","a5a4","a4a3"]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 $stdin.each do |command|
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if command.start_wi= th?("protover"__)

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 $stdout.puts= "feature ping=3D0 setboard=3D1 ics=3D1 usermove=3D1"
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 elsif command.start= _with?("usermove"__)

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 $stdout.puts= "move #{moves[i]}"
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 i+=3D1
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 end
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 $stdout.flush
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 end

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The "protover" thing is= needed to tell the UI program how to
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 initialize
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the protocol, and then every time= a move is made, the UI
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 program sends
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "usermove <some move>&= quot; to my program, which responds with
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "move <my move>".=

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 If I run this by itself, I can ha= ppily enter a few
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 'usermove' commands
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 manually, and get any number of c= anned moves back. However,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 when I run
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 this under the UI, I get an Inter= rupt:

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 bin/winboard.rb:3:in `each': = Interrupt
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 from bin/winboard.rb:3:in `<ma= in>'

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 I know that the UI program is pre= tty reliable, so I'm
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 missing something
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 in the way that I'm handling = IO buffering or something. If
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 you want the
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 nitty gritty details, you can see= them at
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 http://www.gnu.org/softw= are/__xboard/engine-intf.html

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 <http://www.gnu.org/sof= tware/xboard/engine-intf.html> . I'm
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 running on
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 MacOSX. Any suggestions?


=C2=A0 =C2=A0 =C2=A0 =C2=A0 Is it possible that you aren't processing o= ne of the commands
=C2=A0 =C2=A0 =C2=A0 =C2=A0 from the program, and the program is terminatin= g your script,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 perhaps after a timeout or incorrect response? = I'm wondering
=C2=A0 =C2=A0 =C2=A0 =C2=A0 what would show up if you added this:

=C2=A0 =C2=A0 =C2=A0 =C2=A0 else
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0$stderr.print "Unknown comman= d: '#{command}'\n"

=C2=A0 =C2=A0 =C2=A0 =C2=A0 just before the second-last line. Are you handl= ing every
=C2=A0 =C2=A0 =C2=A0 =C2=A0 incoming command as it expects?

=C2=A0 =C2=A0 =C2=A0 =C2=A0 Incidentally, you could always turn those if st= atements into
=C2=A0 =C2=A0 =C2=A0 =C2=A0 case/when, something like:

=C2=A0 =C2=A0 =C2=A0 =C2=A0 case command
=C2=A0 =C2=A0 =C2=A0 =C2=A0 when /^protover/
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ...
=C2=A0 =C2=A0 =C2=A0 =C2=A0 when /^usermove/
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ...
=C2=A0 =C2=A0 =C2=A0 =C2=A0 else
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0$stderr.print "Unknown comman= d: '#{command}'\n"
=C2=A0 =C2=A0 =C2=A0 =C2=A0 end

=C2=A0 =C2=A0 =C2=A0 =C2=A0 This might make it easier if there are a lot of= commands you
=C2=A0 =C2=A0 =C2=A0 =C2=A0 need to respond to.

=C2=A0 =C2=A0 =C2=A0 =C2=A0 Cheers,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 Garth






--20cf307c9fc026b3ae04d800bf40--