From 006f8b49d9ebe1ca334b934d0a127c0029300871 Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Sat, 16 Oct 2021 11:28:38 +0200 Subject: 'writemaybe' command to allow broken pipe errors --- main.cpp | 2 +- process.cpp | 5 +++-- process.h | 2 +- referee.cpp | 21 ++++++++++++++++----- referee.h | 5 +++++ 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/main.cpp b/main.cpp index 24edd5b..306c5cc 100644 --- a/main.cpp +++ b/main.cpp @@ -287,7 +287,7 @@ static void playMatch(Player &p1, Player &p2, int index, const Params ¶ms) { } } else if (auto writeEvent = get_if(&event)) { - if (!procs[writeEvent->player].writeLine(writeEvent->line)) { + if (!procs[writeEvent->player].writeLine(writeEvent->line, writeEvent->allowBrokenPipe)) { cout << "ERROR writing move to player " << writeEvent->player + 1 << " (game " << gameCodeName(p1, p2, index) << ")" << endl; throw StopCompetitionError(); diff --git a/process.cpp b/process.cpp index 6f1ec92..6adc417 100644 --- a/process.cpp +++ b/process.cpp @@ -131,7 +131,7 @@ void Process::unStop() { if (pid != -1) kill(pid, SIGCONT); } -bool Process::writeLine(const string_view line) { +bool Process::writeLine(const string_view line, bool allowBrokenPipe) { if (pid == -1) return false; string str; @@ -144,7 +144,8 @@ bool Process::writeLine(const string_view line) { ssize_t nw = write(infd, str.data() + cursor, str.size() - cursor); if (nw < 0) { if (errno == EINTR) continue; - // perror("write"); + if (allowBrokenPipe && errno == EPIPE) continue; + perror("write"); return false; } cursor += nw; diff --git a/process.h b/process.h index 3505e8e..0588a40 100644 --- a/process.h +++ b/process.h @@ -38,7 +38,7 @@ public: pid_t getPid() const; - bool writeLine(const string_view line); + bool writeLine(const string_view line, bool allowBrokenPipe); optional readLine(); optional readLineTimeout(size_t millis); }; diff --git a/referee.cpp b/referee.cpp index 2701e78..d215c3d 100644 --- a/referee.cpp +++ b/referee.cpp @@ -30,9 +30,9 @@ Referee::Referee(const string_view execname, const vector &players) exit(1); } - proc.writeLine(to_string(players.size())); + proc.writeLine(to_string(players.size()), false); for (const string &p : players) { - proc.writeLine(p); + proc.writeLine(p, false); } } @@ -86,7 +86,7 @@ Referee::Event Referee::nextEvent() { cout << reftag << "write <" << line << ">" << endl; } - if (!proc.writeLine(line)) { + if (!proc.writeLine(line, false)) { cout << reftag << "Referee exited unexpectedly after 'read' command!" << endl; exit(1); } @@ -102,7 +102,18 @@ Referee::Event Referee::nextEvent() { exit(1); } - return WriteEvent{player, command.substr(afterIndex)}; + return WriteEvent{player, false, command.substr(afterIndex)}; + } else if (command.substr(0, 11) == "writemaybe ") { + int player; + size_t afterIndex; + tie(player, afterIndex) = getPlayer(command, "writemaybe", 11); + + if (afterIndex == string::npos) { + cout << reftag << "Protocol violation in 'writemaybe' command: no line!" << endl; + exit(1); + } + + return WriteEvent{player, true, command.substr(afterIndex)}; } else if (command.substr(0, 8) == "gamelog ") { int player; size_t afterIndex; @@ -150,7 +161,7 @@ Referee::Event Referee::nextEvent() { } proc.terminate(); - return ErrorEvent{player, command.substr(6)}; + return ErrorEvent{player, command.substr(afterIndex)}; } else { cout << reftag << "Protocol violation: unknown command '" << command << "'!" << endl; exit(1); diff --git a/referee.h b/referee.h index 1b9d507..11b10ae 100644 --- a/referee.h +++ b/referee.h @@ -35,6 +35,7 @@ public: }; struct WriteEvent { int player; + bool allowBrokenPipe; string line; }; struct GamelogEvent { @@ -77,6 +78,10 @@ Then, the referee has the following commands available: is written directly to the referee afterwards. The first player is 0, the second player is 1, etc. - 'write ': write a line to the player with index . +- 'writemaybe ': write a line to the player with index , + without considering a broken pipe error to be fatal. This is useful for Quit + messages because codecup players tend to exit before getting a formal Quit + sometimes. - 'gamelog ': write a line in the game log indicating that the player with index made the move given by . - 'end ...': signify that the game has ended. The final scores -- cgit v1.2.3-54-g00ecf