summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Smeding <tom@tomsmeding.com>2021-10-16 11:28:38 +0200
committerTom Smeding <tom@tomsmeding.com>2021-10-16 11:28:38 +0200
commit006f8b49d9ebe1ca334b934d0a127c0029300871 (patch)
treefe973fdecedb6f43fccbd8ffb70a5a82f51d59f3
parentc01700906812f949c9088709b6c34307fbf63338 (diff)
'writemaybe' command to allow broken pipe errors
-rw-r--r--main.cpp2
-rw-r--r--process.cpp5
-rw-r--r--process.h2
-rw-r--r--referee.cpp21
-rw-r--r--referee.h5
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 &params) {
}
} else if (auto writeEvent = get_if<Referee::WriteEvent>(&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<string> readLine();
optional<string> 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<string> &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 <player> <line>': write a line to the player with index <player>.
+- 'writemaybe <player> <line>': write a line to the player with index <player>,
+ 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 <player> <line>': write a line in the game log indicating that the
player with index <player> made the move given by <line>.
- 'end <score> <score> ...': signify that the game has ended. The final scores