From 2beaeaa216154b2e59aeaf9ebd3f86800fec3171 Mon Sep 17 00:00:00 2001 From: Xuan Son Nguyen Date: Fri, 24 Jul 2026 07:29:57 +0200 Subject: [PATCH] stderr drain --- tools/server/server-mcp.cpp | 24 +++++++++++++++++++++++- tools/server/server-mcp.h | 4 ++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/tools/server/server-mcp.cpp b/tools/server/server-mcp.cpp index 40fb4eb66d..ddd57f0b59 100644 --- a/tools/server/server-mcp.cpp +++ b/tools/server/server-mcp.cpp @@ -227,13 +227,35 @@ void server_mcp_stdio::writer_loop() { } void server_mcp_stdio::errlog_loop() { + static constexpr size_t ERR_TAIL_MAX = 4096; + std::string buf; char chunk[4096]; for (;;) { size_t n = fread(chunk, 1, sizeof(chunk), proc->err); if (n == 0) { break; } - SRV_DBG("MCP '%s' stderr: %.*s", name.c_str(), (int) n, chunk); + buf.append(chunk, n); + + size_t pos; + while ((pos = buf.find('\n')) != std::string::npos) { + std::string line = buf.substr(0, pos); + buf.erase(0, pos + 1); + if (!line.empty() && line.back() == '\r') { + line.pop_back(); + } + if (line.empty()) { + continue; + } + SRV_DBG("MCP '%s' stderr: %s\n", name.c_str(), line.c_str()); + + std::lock_guard lk(err_mu); + err_tail += line; + err_tail += '\n'; + if (err_tail.size() > ERR_TAIL_MAX) { + err_tail.erase(0, err_tail.size() - ERR_TAIL_MAX); + } + } } } diff --git a/tools/server/server-mcp.h b/tools/server/server-mcp.h index afc270c816..24fd517af3 100644 --- a/tools/server/server-mcp.h +++ b/tools/server/server-mcp.h @@ -117,6 +117,10 @@ private: // cleared by close() or by the reader on stdout EOF; read without rpc_mutex std::atomic running{false}; + // bounded tail of the child's stderr, for diagnostics when it dies + std::mutex err_mu; + std::string err_tail; + void reader_loop(); void writer_loop(); void errlog_loop();