stellar

UCI 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;