Skip to content

Instantly share code, notes, and snippets.

@socketpair
Last active July 5, 2025 11:29
Show Gist options
  • Select an option

  • Save socketpair/913f4384fe3fea37b431a58943adbdaa to your computer and use it in GitHub Desktop.

Select an option

Save socketpair/913f4384fe3fea37b431a58943adbdaa to your computer and use it in GitHub Desktop.
Сегфолт от нейросети
// echo_server.cpp – minimalist echo‑server using C++23 coroutines + io_uring // g++ -std=c++23 -Wall -O2 echo_server.cpp -luring -o echo_server
#include <coroutine> #include <liburing.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <cstring> #include <cerrno> #include <system_error> #include <vector> #include <iostream> #include <memory>
//--------------------------------------------------------------------- // Small RAII helpers ------------------------------------------------- //--------------------------------------------------------------------- class UniqueFd { int fd_ = -1; public: UniqueFd() = default; explicit UniqueFd(int fd) : fd_(fd) {} UniqueFd(const UniqueFd&) = delete; UniqueFd& operator=(const UniqueFd&) = delete; UniqueFd(UniqueFd&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; } UniqueFd& operator=(UniqueFd&& other) noexcept { if (this != &other) { reset(); fd_ = other.fd_; other.fd_ = -1; } return *this; } ~UniqueFd() { reset(); } int get() const { return fd_; } int release() { int tmp = fd_; fd_ = -1; return tmp; } void reset(int fd = -1) { if (fd_ != -1) ::close(fd_); fd_ = fd; } explicit operator bool() const { return fd_ != -1; } };
//--------------------------------------------------------------------- // A very small coroutine/awaitable framework for io_uring ------------ //--------------------------------------------------------------------- struct IoContext; // fwd
struct IoOperationBase { IoContext* ctx; // owning context std::coroutine_handle<> handle; // coroutine to resume int result = 0; // cqe->res will end up here };
struct IoContext { explicit IoContext(unsigned entries = 256) { if (io_uring_queue_init(entries, &ring, 0) != 0) { throw std::system_error(errno, std::system_category(), "io_uring_queue_init"); } } ~IoContext() { io_uring_queue_exit(&ring); }
// submit & loop ----------------------------------------------------- void run() { while (!tasks.empty()) { io_uring_submit(&ring); io_uring_cqe* cqe; int ret = io_uring_wait_cqe(&ring, &cqe); if (ret < 0) throw std::system_error(-ret, std::system_category(), "io_uring_wait_cqe");
auto* op = reinterpret_cast<IoOperationBase*>(io_uring_cqe_get_data(cqe));
op->result = cqe->res;
io_uring_cqe_seen(&ring, cqe);
op->handle.resume();
}
}
template<typename T> void addTask(std::coroutine_handle<T> h) { tasks.push_back(h); }
io_uring ring; std::vector<std::coroutine_handle<>> tasks; // keep root coroutines alive };
//--------------------------------------------------------------------- // Awaitables --------------------------------------------------------- //--------------------------------------------------------------------- struct AcceptAwaitable : IoOperationBase { int listen_fd; sockaddr_in* addr; socklen_t* addrlen;
bool await_ready() const noexcept { return false; } void await_suspend(std::coroutine_handle<> h) { handle = h; io_uring_sqe* sqe = io_uring_get_sqe(&ctx->ring); if (!sqe) throw std::runtime_error("get_sqe failed"); io_uring_prep_accept(sqe, listen_fd, reinterpret_cast<sockaddr*>(addr), addrlen, 0); io_uring_sqe_set_data(sqe, this); } int await_resume() { if (result < 0) throw std::system_error(-result, std::system_category(), "accept"); return result; } };
struct RecvAwaitable : IoOperationBase { int fd; void* buf; size_t len;
bool await_ready() const noexcept { return false; } void await_suspend(std::coroutine_handle<> h) { handle = h; io_uring_sqe* sqe = io_uring_get_sqe(&ctx->ring); if (!sqe) throw std::runtime_error("get_sqe failed"); io_uring_prep_recv(sqe, fd, buf, len, 0); io_uring_sqe_set_data(sqe, this); } int await_resume() { if (result < 0) throw std::system_error(-result, std::system_category(), "recv"); return result; } };
struct SendAwaitable : IoOperationBase { int fd; const void* buf; size_t len;
bool await_ready() const noexcept { return false; } void await_suspend(std::coroutine_handle<> h) { handle = h; io_uring_sqe* sqe = io_uring_get_sqe(&ctx->ring); if (!sqe) throw std::runtime_error("get_sqe failed"); io_uring_prep_send(sqe, fd, buf, len, MSG_NOSIGNAL); io_uring_sqe_set_data(sqe, this); } int await_resume() { if (result < 0) throw std::system_error(-result, std::system_category(), "send"); return result; } };
//--------------------------------------------------------------------- // Task type ---------------------------------------------------------- //--------------------------------------------------------------------- struct Task { struct promise_type { Task get_return_object() { return Task(std::coroutine_handle<promise_type>::from_promise(*this)); } std::suspend_always initial_suspend() noexcept { return {}; } std::suspend_always final_suspend() noexcept { return {}; } void return_void() {} void unhandled_exception() { std::terminate(); } };
explicit Task(std::coroutine_handle<promise_type> h) : handle(h) {} Task(const Task&) = delete; Task(Task&&) noexcept = default; ~Task() { if (handle) handle.destroy(); }
void start(IoContext& ctx) { ctx.addTask(handle); handle.resume(); }
private: std::coroutine_handle<promise_type> handle; };
//--------------------------------------------------------------------- // Echo session ------------------------------------------------------- //--------------------------------------------------------------------- Task echo_session(IoContext& ctx, int client_fd) { UniqueFd sock{client_fd}; constexpr size_t BUF_SIZE = 4096; char buffer[BUF_SIZE];
while (true) { int n = co_await RecvAwaitable{&ctx, {}, 0, sock.get(), buffer, BUF_SIZE}; if (n == 0) break; // client closed co_await SendAwaitable{&ctx, {}, 0, sock.get(), buffer, static_cast<size_t>(n)}; } }
//--------------------------------------------------------------------- // Accept loop -------------------------------------------------------- //--------------------------------------------------------------------- Task accept_loop(IoContext& ctx, int listen_fd) { while (true) { sockaddr_in addr; socklen_t len = sizeof(addr); int client = co_await AcceptAwaitable{&ctx, {}, 0, listen_fd, &addr, &len}; echo_session(ctx, client).start(ctx); } }
//--------------------------------------------------------------------- // Setup listening socket -------------------------------------------- //--------------------------------------------------------------------- UniqueFd make_listen_socket(uint16_t port) { int fd = ::socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) throw std::system_error(errno, std::system_category(), "socket"); UniqueFd sock{fd};
int opt = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) throw std::system_error(errno, std::system_category(), "setsockopt");
sockaddr_in addr{}; addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(port); if (bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) throw std::system_error(errno, std::system_category(), "bind"); if (listen(fd, SOMAXCONN) < 0) throw std::system_error(errno, std::system_category(), "listen");
return sock; }
//--------------------------------------------------------------------- // main --------------------------------------------------------------- //--------------------------------------------------------------------- int main(int argc, char* argv[]) { uint16_t port = 12345; if (argc > 1) port = static_cast<uint16_t>(std::stoi(argv[1]));
try { UniqueFd listen_fd = make_listen_socket(port); IoContext ctx; accept_loop(ctx, listen_fd.get()).start(ctx); std::cout << "Echo‑server listening on port " << port << "...\n"; ctx.run(); } catch (const std::exception& ex) { std::cerr << "Fatal: " << ex.what() << "\n"; return 1; } return 0; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment