Treat 'quit', 'force' and '?' commands immediately
authorH.G.Muller <hgm@hgm-xboard.(none)>
Wed, 30 Nov 2016 08:02:50 +0000 (09:02 +0100)
committerH.G.Muller <hgm@hgm-xboard.(none)>
Wed, 30 Nov 2016 08:18:54 +0000 (09:18 +0100)
The blocking of input during thinking made it also insensitive to 'quit'.
This would cause hanging engine processes when the GUI was closed and would
kill the adapter because it did not respond to 'quit' in time. The Sync()
call that waits for the engine's 'bestmove' is now deferred until after
reading input (executed conditionally through a 'think' flag, so that
it only happens during thinking), so that we can peek at the first command
that arrives during thinking. If it is one of the 'immediate' commands
(?, quit or force), a 'stop' command is sent to the engine before we
start waiting for the 'bestmove', which then never should take long.
 Draw offers could potentially arrive during thinking as well, interefering
with this mechanism by eclipsing a following ?/quit/force. As these would
just set the drawOffer flag for processing during the next move, these
are now fully processed immediately.

UCI2WB.c

index c13ea34..2971c3f 100644 (file)
--- a/UCI2WB.c
+++ b/UCI2WB.c
@@ -398,7 +398,7 @@ GUI2Engine()
     char line[256], command[256], *p, *q, *r, mySide, searching = 0;\r
 \r
     while(1) {\r
-       int i, x;\r
+       int i, x, think=0;\r
 \r
        if((computer == stm || computer == ANALYZE && !searching) && !suspended) {\r
            DPRINT("# start search\n");\r
@@ -412,13 +412,18 @@ GUI2Engine()
                    for(i=1; i<nr; i++) if(on[i]) EPRINT((f, " %s", moveMap[i]))\r
                }\r
                EPRINT((f, "\n")) searching = 1; // suppresses spurious commands during analysis starting new searches\r
-           } else { pause = 2; StartSearch(""); fflush(stdout); fflush(toE); Sync(PAUSE); } // block input during thinking\r
+           } else pause = think = 2, StartSearch(""); // request suspending of input processing while thinking\r
        }\r
       nomove:\r
        fflush(toE); fflush(stdout);\r
        i = 0; while((x = getchar()) != EOF && (line[i] = x) != '\n') i++;\r
        line[++i] = 0; if(x == EOF) { printf("# EOF\n"); EPRINT((f, "# quit\n")) exit(-1); }\r
        sscanf(line, "%s", command);\r
+       if(!strcmp(command, "offer")) { drawOffer = 1; goto nomove; } // backlogged anyway, so this can be done instantly\r
+       if(think) {      // command arrived during thinking; order abort for 'instant commands'\r
+           if(!strcmp(command, "quit") || !strcmp(command, "force") || !strcmp(command, "?")) { EPRINT((f, "# stop\n")); fflush(toE); }\r
+           Sync(PAUSE); // block processing of input during thinking\r
+       }\r
        if(!strcmp(command, "new")) {\r
            computer = BLACK; moveNr = 0; depth = -1; move[0][0] = 0;\r
            stm = WHITE; strcpy(iniPos, "position startpos"); frc &= ~1;\r
@@ -539,7 +544,6 @@ GUI2Engine()
        else if(!strcmp(command, "st"))     sscanf(line, "st %d", &sTime), sTime = 1000*sTime - 30, inc = 0, sTime /= unit;\r
        else if(!strcmp(command, "name"))   { if(namOpt) EPRINT((f, "# setoption name UCI_Opponent value none none %s %s", comp ? "computer" : "human", line+5)) }\r
        else if(!strcmp(command, "computer")) comp = 1;\r
-       else if(!strcmp(command, "offer"))  drawOffer = 1;\r
        else if(!strcmp(command, "result")) { if(sc == 's') EPRINT((f, "# gameover %s\n", line[8] == '/' ? "draw" : (line[7] == '0') == mySide ? "win" : "lose")) }\r
        else if(!strcmp(command, "quit"))   { EPRINT((f, "# quit\n")) fflush(toE), exit(0); }\r
     }\r