From 5cd2226735d28f52f32f8adeea832989c47cd359 Mon Sep 17 00:00:00 2001 From: Moritz Raguschat Date: Sun, 22 Mar 2026 15:26:58 +0700 Subject: [PATCH 1/2] fix poll() / getline() buffered IO desync --- src/mcp/mcp.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/mcp/mcp.c b/src/mcp/mcp.c index bdfdae8..3e79140 100644 --- a/src/mcp/mcp.c +++ b/src/mcp/mcp.c @@ -2389,16 +2389,15 @@ int cbm_mcp_server_run(cbm_mcp_server_t *srv, FILE *in, FILE *out) { continue; } #else - struct pollfd pfd = {.fd = fd, .events = POLLIN}; - int pr = poll(&pfd, 1, STORE_IDLE_TIMEOUT_S * 1000); - - if (pr < 0) { - break; /* error or signal */ - } - if (pr == 0) { - /* Timeout — evict idle store to free resources */ - cbm_mcp_server_evict_idle(srv, STORE_IDLE_TIMEOUT_S); - continue; + int has_buffered = (in->_IO_read_ptr < in->_IO_read_end); // glibc-specific + if (!has_buffered) { + struct pollfd pfd = {.fd = fd, .events = POLLIN}; + int pr = poll(&pfd, 1, STORE_IDLE_TIMEOUT_S * 1000); + if (pr < 0) break; + if (pr == 0) { + cbm_mcp_server_evict_idle(srv, STORE_IDLE_TIMEOUT_S); + continue; + } } #endif From 21e9f730f07bbea47bf391540682cb64706f0f7e Mon Sep 17 00:00:00 2001 From: Moritz Raguschat Date: Sun, 22 Mar 2026 16:30:10 +0700 Subject: [PATCH 2/2] Fix file buffer check on MacOS / BSD (hopefully) --- src/mcp/mcp.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/mcp/mcp.c b/src/mcp/mcp.c index 3e79140..cdcf2bb 100644 --- a/src/mcp/mcp.c +++ b/src/mcp/mcp.c @@ -2389,7 +2389,13 @@ int cbm_mcp_server_run(cbm_mcp_server_t *srv, FILE *in, FILE *out) { continue; } #else - int has_buffered = (in->_IO_read_ptr < in->_IO_read_end); // glibc-specific +#ifdef __GLIBC__ + int has_buffered = (in->_IO_read_ptr < in->_IO_read_end); +#else + /* macOS / BSD: use __srget-style check. + * fp->_r is the count of unread bytes in the buffer. */ + int has_buffered = (in->_r > 0); +#endif if (!has_buffered) { struct pollfd pfd = {.fd = fd, .events = POLLIN}; int pr = poll(&pfd, 1, STORE_IDLE_TIMEOUT_S * 1000);