From 99c8c5430513460d625bbeb59281c3e5812d250e Mon Sep 17 00:00:00 2001 From: "H.G.Muller" Date: Tue, 18 Jun 2019 12:48:20 +0200 Subject: [PATCH] Kill engines that do not respond to 'quit' in time If an engine process is still alive 50ms after the adapter received a 'quit' command, it will now be killed. This is done by the GUI thread (which now also causes the adapter to exit), because the engine thread might be tied up in listening to an engine that has no intention to respond to 'stop'. (Which would be a necessary condition for the engine thread to relay the queued 'quit' command.) --- UCI2WB.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/UCI2WB.c b/UCI2WB.c index 10b1f6d..4ca1598 100644 --- a/UCI2WB.c +++ b/UCI2WB.c @@ -18,16 +18,19 @@ # include HANDLE process; DWORD thread_id; + void Bury(int s) { if(WaitForSingleObject(process, 1000*s+50) != WAIT_OBJECT_0) TerminateProcess(process, 0); } #else # include # include # include # define NO_ERROR 0 # include +# include int GetTickCount() // with thanks to Tord { struct timeval t; gettimeofday(&t, NULL); return t.tv_sec*1000 + t.tv_usec/1000; } //# include int Sleep(int msec) { return usleep(1000*msec); } + int pid; void Bury(int msec) { Sleep(msec+50); if(waitpid(-1, NULL, WNOHANG) <= 0) kill(pid, SIGKILL); } #endif #include #include @@ -52,10 +55,9 @@ int statDepth, statScore, statNodes, statTime, currNr, size, collect, nr, sm, in char currMove[20], moveMap[500][10], /* for analyze mode */ canPonder[20], threadOpt[20], varList[8000], anaOpt[20], checkOptions[8192] = "Ponder"; char pvs[99][999], board[100]; // XQ board for UCCI char *nameWord = "name ", *valueWord = "value ", *wTime = "w", *bTime = "b", *wInc = "winc", *bInc = "binc", newGame; // keywords that differ in UCCI -int unit = 1, drawOffer, scores[99], mpvSP, maxDepth, ponderAlways, newCnt, priority; +int unit = 1, drawOffer, scores[99], mpvSP, maxDepth, ponderAlways, newCnt, priority, killDelay; FILE *toE, *fromE, *fromF; -int pid; char *strcasestr (char *p, char *q) { while(*p) { char *r=p++, *s=q; while(tolower(*r++) == tolower(*s) && *s) s++; if(!*s) return p-1; } return NULL; } @@ -533,7 +535,7 @@ GUI2Engine() p = line; while(qEnd < queue+10000 && (*qEnd++ = *p++) != '\n') {} Sync(WAKEUP); // when 'stop' doesn't catch engine's attention in reasonable time, so the GUI might kill us: - if(!strcmp(command, "quit")) { Sleep(500); EPRINT((f, "quit\n")); } // make sure 'quit' is still sent + if(!strcmp(command, "quit")) { Bury(killDelay); exit(0); } // kill the engine and exit } } } @@ -632,7 +634,7 @@ DoCommand () if(sc == 's') EPRINT((f, "# gameover %s\n", line[8] == '/' ? "draw" : (line[7] == '0') == mySide ? "win" : "lose")) computer = NONE; } - else if(!strcmp(command, "quit")) { EPRINT((f, "# quit\n")) fflush(toE), exit(atoi(line+4)); } + else if(!strcmp(command, "quit")) { EPRINT((f, "# quit\n")) fflush(toE); } else printf("Error (unknown command): %s\n", command); fflush(stdout); @@ -704,7 +706,6 @@ StartEngine(char *cmdLine, char *dir) CloseHandle(hChildStdoutWr); process = piProcInfo.hProcess; - pid = piProcInfo.dwProcessId; fromE = (FILE*) _fdopen( _open_osfhandle((long)hChildStdoutRd, _O_TEXT|_O_RDONLY), "r"); toE = (FILE*) _fdopen( _open_osfhandle((long)hChildStdinWr, _O_WRONLY), "w"); #else -- 2.17.1