Problems Debugging UCI GUI Commands...

Discussion of chess software programming and technical issues.

Moderator: Ras

User avatar
Steve Maughan
Posts: 1315
Joined: Wed Mar 08, 2006 8:28 pm
Location: Florida, USA

Problems Debugging UCI GUI Commands...

Post by Steve Maughan »

Hi All,

I have a bug in Maverick which is driving me nuts. I realize Forums are not usually a great method of debugging but maybe, just maybe, one of you have come across a similar nasty bug in your code.

Here the situation...

Maverick now plays (weak) chess. But when I leave it to play in Engine vs. Engine mode it crashes after a number of games. The situation where is crashes is always the same. It's always late in the game after the GUI (in this case Shredder) send a long "position" command (usually just over 1024 characters). As far as I can tell Maverick processes the "position" command. However it "misses" the "go" command and instead receives a zero length string (see below).

Maverick has no problems when I set-up the position as a test routine - so I don't think this is a problem with the chess logic.

My first thought was this is some form of overrun. But I have 4096 as the length of the input string.

I should also say I have one thread which waits for commands (gets(input_string)). When it receives the position command it processes it and then waits.

I also have the buffers set to zero using the following code:

Code: Select all

setbuf(stdout, NULL);
setbuf(stdin, NULL);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stdin, NULL, _IONBF, 0);
Could the buffers be too small i.e. are input characters being lost due to no buffer space?

I also note there are times when Shredder restarts the Maverick and immediately re-sends the offending string, which also leads to a crash. Is there any way of simulating stdin commands in debug (apart from typing fast!).

Thanks,

Desperate debugging regards,

Steve

Code: Select all

Sent     >> info score cp 130 time 16 depth 5 seldepth 8 nodes 3614 pv d5f6 d7e6 f6d5 e1b4 h5g4
Sent     >> info score cp 122 time 16 depth 6 seldepth 10 nodes 22498 pv d5f6 d7d6 f6d5 e1f2 d5f6 f2d4
Sent     >> info score cp 122 time 32 depth 7 seldepth 11 nodes 97392 pv d5f6 d7d6 f6d5 e1f2 h5g5 f2d4 d5f6
Sent     >> info score cp 122 time 47 depth 7 seldepth 12 nodes 212004 pv d5f6 d7d6 f6d5 e1f2 h5g5 f2d4 d5f6
Sent     >> info nodes 212004 nps 4510723
Sent     >> bestmove d5f6 ponder d7d6
Received >> position startpos moves e2e4 c7c5 g1f3 e7e6 d2d4 c5d4 f3d4 g8f6 b1c3 d7d6 g2g3 a7a6 f1g2 d8c7 e1g1 b8c6 f1e1 a8b8 d4c6 b7c6 c3a4 f6d7 b2b3 f8e7 c1b2 e6e5 a4c3 d7c5 b2a3 c8e6 a3c5 d6c5 g2f1 e8g8 f1d3 f8d8 d1f3 c7a5 c3e2 g7g6 h2h4 b8b7 h4h5 e7g5 e1d1 h7h6 g1f1 a5a3 h5g6 f7g6 e2c3 a3a5 c3b1 b7f7 f3e2 h6h5 f2f3 d8f8 b1d2 a5c3 f1g2 a6a5 d2c4 f7f3 e2e1 c3e1 d1e1 h5h4 g3h4 g5h4 e1e3 f3e3 c4e3 h4f2 d3c4 e6c4 e3c4 f2d4 a1f1 f8f1 g2f1 g8f7 c4a5 d4c3 a5c6 g6g5 f1e2 f7e6 c6d8 e6e7 d8c6 e7e6 c6d8 e6e7 e2d3 g5g4 d8c6 e7e6 c6d8 e6e7 d8c6 e7e6 d3e2 e6d7 c6a7 g4g3 a7b5 c3d2 e2f3 d2e1 b5a3 d7e6 a3c4 e1f2 a2a4 f2d4 a4a5 e6d7 f3g3 d7c6 c4d2 c6b5 d2c4 b5c6 g3g2 c6b5 g2h2 d4c3 h2g3 c3a5 g3g4 a5c3 c4e3 c3d4 e3d5 d4b2 c2c4 b5c6 d5f6 b2c3 g4f3 c6b7 f3e2 b7c8 e2d1 c3a5 f6d5 c8b7 d1e2 b7b8 e2f3 b8b7 f3g4 b7c6 g4f5 c6d6 f5g4 d6c6 g4f5 c6d6 f5g6 a5e1 d5f6 d6e6 f6d5 e6d6 d5f6 d6e6 g6g7 e1d2 f6d5 d2e1 d5c7 e6d7 c7d5 d7e6 g7h6 e1f2 h6g6 f2d4 d5c7 e6d7 c7d5 d7e6 g6g7 d4f2 d5c7 e6d7 c7d5 d7e6 g7h6 e6d7 d5f6 d7e6 f6d5 e6d7 h6h5 f2e1 d5f6 d7d6  ***LONG POSITION STRING FOLLOWED BY A ZERO LENGTH STRING (WHICH IS THE GUI'S "GO" COMMAND***
Received >> 
Received >> uci
Sent     >> id name Maverick 0.05 64 bit
Sent     >> id author Steve Maughan
Sent     >> option name Hash type spin default 2 min 2 max 1024
Sent     >> option name Ponder type check default true
Sent     >> option name OwnBook type check default true
Sent     >> option name Opening Book type combo default TDDBII.bin var Diffusion 1.0.9.bin var TDDBII.bin
Sent     >> option name UCI_EngineAbout type string default Maverick (v0.05 64 bit) by Steve Maughan www.chessprogramming.net
Sent     >> uciok
Received >> debug on
Received >> setoption name Hash value 128
Received >> setoption name Ponder value true
Received >> setoption name OwnBook value true
Received >> isready
Sent     >> readyok
Received >> ucinewgame
Received >> isready
Sent     >> readyok
Received >> position startpos moves e2e4 c7c5 g1f3 e7e6 d2d4 c5d4 f3d4 g8f6 b1c3 d7d6 g2g3 a7a6 f1g2 d8c7 e1g1 b8c6 f1e1 a8b8 d4c6 b7c6 c3a4 f6d7 b2b3 f8e7 c1b2 e6e5 a4c3 d7c5 b2a3 c8e6 a3c5 d6c5 g2f1 e8g8 f1d3 f8d8 d1f3 c7a5 c3e2 g7g6 h2h4 b8b7 h4h5 e7g5 e1d1 h7h6 g1f1 a5a3 h5g6 f7g6 e2c3 a3a5 c3b1 b7f7 f3e2 h6h5 f2f3 d8f8 b1d2 a5c3 f1g2 a6a5 d2c4 f7f3 e2e1 c3e1 d1e1 h5h4 g3h4 g5h4 e1e3 f3e3 c4e3 h4f2 d3c4 e6c4 e3c4 f2d4 a1f1 f8f1 g2f1 g8f7 c4a5 d4c3 a5c6 g6g5 f1e2 f7e6 c6d8 e6e7 d8c6 e7e6 c6d8 e6e7 e2d3 g5g4 d8c6 e7e6 c6d8 e6e7 d8c6 e7e6 d3e2 e6d7 c6a7 g4g3 a7b5 c3d2 e2f3 d2e1 b5a3 d7e6 a3c4 e1f2 a2a4 f2d4 a4a5 e6d7 f3g3 d7c6 c4d2 c6b5 d2c4 b5c6 g3g2 c6b5 g2h2 d4c3 h2g3 c3a5 g3g4 a5c3 c4e3 c3d4 e3d5 d4b2 c2c4 b5c6 d5f6 b2c3 g4f3 c6b7 f3e2 b7c8 e2d1 c3a5 f6d5 c8b7 d1e2 b7b8 e2f3 b8b7 f3g4 b7c6 g4f5 c6d6 f5g4 d6c6 g4f5 c6d6 f5g6 a5e1 d5f6 d6e6 f6d5 e6d6 d5f6 d6e6 g6g7 e1d2 f6d5 d2e1 d5c7 e6d7 c7d5 d7e6 g7h6 e1f2 h6g6 f2d4 d5c7 e6d7 c7d5 d7e6 g6g7 d4f2 d5c7 e6d7 c7d5 d7e6 g7h6 e6d7 d5f6 d7e6 f6d5 e6d7 h6h5 f2e1 d5f6 d7e6  ***SAME STRING AND SAME RESULT***
Received >> 
Received >> uci
Sent     >> id name Maverick 0.05 64 bit
Sent     >> id author Steve Maughan
Sent     >> option name Hash type spin default 2 min 2 max 1024
Sent     >> option name Ponder type check default true
Sent     >> option name OwnBook type check default true
Sent     >> option name Opening Book type combo default TDDBII.bin var Diffusion 1.0.9.bin var TDDBII.bin
Sent     >> option name UCI_EngineAbout type string default Maverick (v0.05 64 bit) by Steve Maughan www.chessprogramming.net
Sent     >> uciok
User avatar
Steve Maughan
Posts: 1315
Joined: Wed Mar 08, 2006 8:28 pm
Location: Florida, USA

Re: Problems Debugging UCI GUI Commands...

Post by Steve Maughan »

It's Fixed!

It was a buffer overflow.

Somewhat ironically it was in the "write-debug-log" routine!

All's working regards,

Steve
lucasart
Posts: 3243
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Problems Debugging UCI GUI Commands...

Post by lucasart »

Steve Maughan wrote:It's Fixed!

It was a buffer overflow.

Somewhat ironically it was in the "write-debug-log" routine!

All's working regards,

Steve
The answer was in the question
Could the buffers be too small i.e. are input characters being lost due to no buffer space?
Anyway, I'm glad you fixed it. It's annoying to have bugs that are hard to reproduce and debug.

If you really want to be clean, and not rely on a fixed size buffer, write a function like

Code: Select all

get_token()
that reads from stdin using getchar(), by word (skipping blanks) and returns an empty string when end of file reached (or end of file). And then read your position command token by token, instead of reading it at once in a big buffer and parsing it after.
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
User avatar
emadsen
Posts: 441
Joined: Thu Apr 26, 2012 1:51 am
Location: Oak Park, IL, USA
Full name: Erik Madsen

Re: Problems Debugging UCI GUI Commands...

Post by emadsen »

It's Fixed! It was a buffer overflow.
Glad you found the problem.
If you really want to be clean, and not rely on a fixed size buffer, write a function like
Code:
get_token()

that reads from stdin using getchar(), by word (skipping blanks) and returns an empty string when end of file reached (or end of file). And then read your position command token by token, instead of reading it at once in a big buffer and parsing it after.

Agree. That's what I do in my engine.

Code: Select all

private void DispatchCommand(string CommandLine)
{
    Tokens colTokens = new Tokens(CommandLine);
    if (colTokens.Count == 0)
    {
        // No tokens found.
        return;
    }
    // Determine whether to dispatch command on main thread or async thread.
    switch (colTokens[0].Value.ToLower(CultureInfo.InvariantCulture))
    {
        case "go":
            DispatchOnAsyncThread(colTokens);
            break;
        default:
            DispatchOnMainThread(colTokens);
            break;
    }
}
Erik Madsen | My C# chess engine: https://www.madchess.net