stellarUCI Chess engine written in C++20 |
git clone git://git.dimitrijedobrota.com/stellar.git |
Log | Files | Refs | README | LICENSE | |
commit | cf910ba4f353e80592135912e4d8b42415bffb1e |
parent | 4e698dee2fb03a902881aa74a33092053a82612e |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Wed, 6 Dec 2023 20:48:12 +0000 |
Fix leaking pipes
Diffstat:M | CMakeLists.txt | | | +- |
M | src/arena/engine.cpp | | | +++++++++++++++++++++++-------------------- |
M | src/arena/engine.hpp | | | ++++++++++++++++++++- |
3 files changed, 44 insertions(+), 22 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(
Stellar
VERSION 1.1.1
VERSION 1.1.2
DESCRIPTION "Chess engine written in C++"
HOMEPAGE_URL https://git.dimitrijedobrota.com/stellar.git
LANGUAGES CXX
diff --git a/src/arena/engine.cpp b/src/arena/engine.cpp
@@ -6,26 +6,31 @@
#include <sys/wait.h>
#include <unistd.h>
uint16_t Engine::id_t = 0;
Engine::Engine(const char *file) : file(file) {
if (pipe(fd_to) < 0 || pipe(fd_from) < 0) {
Engine::Pipes::Pipes() {
if (pipe(fd) < 0 || pipe(fd) < 0) {
logger::error("pipe");
throw std::runtime_error("pipe failed");
}
}
if ((engine_pid = fork()) > 0) {
void Engine::Pipes::close() {
if (::close(fd[0]) < 0 || ::close(fd[1])) {
logger::error("close");
throw std::runtime_error("close failed");
}
closed = true;
}
uint16_t Engine::id_t = 0;
Engine::Engine(const char *file) : file(file) {
if ((engine_pid = fork()) == 0) {
start_engine();
} else if (engine_pid < 0) {
logger::error("fork");
throw std::runtime_error("fork failed");
}
if (close(fd_to[0]) < 0 || close(fd_from[1])) {
logger::error("close");
throw std::runtime_error("close failed");
}
send("uci");
logger::log(std::format("Engine {}: waiting for uciok from {}", id, file));
@@ -47,8 +52,8 @@ Engine::~Engine() {
waitpid(engine_pid, nullptr, 0);
// kill(engine_pid, SIGKILL);
if (close(fd_to[1]) < 0) logger::error("close");
if (close(fd_from[0]) < 0) logger::error("close");
pipeFrom.close();
pripeTo.close();
logger::log("Engine: destroyed", logger::Debug);
}
@@ -57,7 +62,7 @@ void Engine::send(std::string &&command) {
const char *buffer = command.data();
size_t to_write = command.size();
while (to_write) {
ssize_t size = write(fd_to[1], buffer, to_write);
ssize_t size = write(pripeTo[1], buffer, to_write);
if (size == -1) {
logger::error("write");
throw std::runtime_error("write failed");
@@ -80,7 +85,7 @@ std::string Engine::receive() {
return response;
}
if ((size = read(fd_from[0], rb + rb_size, sizeof(rb) - rb_size)) == -1) {
if ((size = read(pipeFrom[0], rb + rb_size, sizeof(rb) - rb_size)) == -1) {
logger::error("read");
throw std::runtime_error("read failed");
}
@@ -105,16 +110,14 @@ std::string Engine::receive() {
}
[[noreturn]] void Engine::start_engine() {
if (close(fd_to[1]) < 0 || close(fd_from[0])) {
logger::error("close");
throw std::runtime_error("close failed");
}
if (dup2(fd_to[0], 0) < 0 || dup2(fd_from[1], 1) < 0) {
if (dup2(pripeTo[0], 0) < 0 || dup2(pipeFrom[1], 1) < 0) {
logger::error("dup2");
throw std::runtime_error("dup2 failed");
}
pipeFrom.close();
pripeTo.close();
execl(file, file, (char *)nullptr);
logger::error("execl");
throw std::runtime_error("execl failed");
diff --git a/src/arena/engine.hpp b/src/arena/engine.hpp
@@ -18,10 +18,29 @@ class Engine {
std::string receive();
private:
class Pipes {
public:
Pipes();
Pipes(const Pipes &) = delete;
Pipes &operator=(const Pipes &) = delete;
~Pipes() {
if (!closed) close();
}
void close();
int operator[](int idx) { return fd[idx]; }
private:
int fd[2]{};
bool closed = false;
};
[[noreturn]] void start_engine();
const char *file = nullptr;
int fd_to[2]{}, fd_from[2]{};
Pipes pipeFrom, pripeTo;
pid_t engine_pid;
std::string name, author;