@chrishamm
I found that adding an overflow check in void HttpResponder::HandleGCodeReply(const char *_ecv_array reply) noexcept will help to mitiage the problem. I don't know yet if it is solved in the long run.
From e4799bc4e3343878d035cb0074b2f37cfbf524be Mon Sep 17 00:00:00 2001
From: Tim Schneider <tim@schneider.engineering>
Date: Tue, 11 Feb 2025 12:03:55 +0100
Subject: [PATCH] - check for OutputBuffer overflow in
HttpResponder::HandleGCodeReply
---
src/Networking/HttpResponder.cpp | 14 ++++++++++++++
src/Networking/NetworkResponder.cpp | 2 +-
src/Networking/NetworkResponder.h | 2 +-
3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/src/Networking/HttpResponder.cpp b/src/Networking/HttpResponder.cpp
index b9deb5e6..b0ed4e51 100644
--- a/src/Networking/HttpResponder.cpp
+++ b/src/Networking/HttpResponder.cpp
@@ -1536,6 +1536,20 @@ void HttpResponder::Diagnostics(MessageType mt) const noexcept
}
buffer->cat(reply);
+
+ if (buffer->HadOverflow())
+ {
+ // We ran out of buffers at some point.
+ ReportOutputBufferExhaustion(__FILE__, __LINE__);
+
+ // Discard pending replies
+ while (!gcodeReply.IsEmpty())
+ {
+ OutputBuffer *buf = gcodeReply.Pop();
+ OutputBuffer::ReleaseAll(buf);
+ }
+ }
+
clientsServed = 0;
seq++;
}
diff --git a/src/Networking/NetworkResponder.cpp b/src/Networking/NetworkResponder.cpp
index a4c025d3..aeaee3c7 100644
--- a/src/Networking/NetworkResponder.cpp
+++ b/src/Networking/NetworkResponder.cpp
@@ -192,7 +192,7 @@ IPAddress NetworkResponder::GetRemoteIP() const noexcept
return (skt == nullptr) ? IPAddress() : skt->GetRemoteIP();
}
-void NetworkResponder::ReportOutputBufferExhaustion(const char *_ecv_array sourceFile, int line) noexcept
+/*static*/ void NetworkResponder::ReportOutputBufferExhaustion(const char *_ecv_array sourceFile, int line) noexcept
{
if (reprap.Debug(Module::Webserver))
{
diff --git a/src/Networking/NetworkResponder.h b/src/Networking/NetworkResponder.h
index 97633ac2..47324738 100644
--- a/src/Networking/NetworkResponder.h
+++ b/src/Networking/NetworkResponder.h
@@ -69,7 +69,7 @@ protected:
virtual void ConnectionLost() noexcept;
IPAddress GetRemoteIP() const noexcept;
- void ReportOutputBufferExhaustion(const char *_ecv_array sourceFile, int line) noexcept;
+ static void ReportOutputBufferExhaustion(const char *_ecv_array sourceFile, int line) noexcept;
static Platform& GetPlatform() noexcept { return reprap.GetPlatform(); }
static Network& GetNetwork() noexcept { return reprap.GetNetwork(); }
--
2.39.2.windows.1
you can see in the following debug log for Module Webserver that this line is triggered sometimes
Ran out of output buffers at ../src/Networking/HttpResponder.cpp(1543)<\n>
HTTP req, command words { GET /rr_gcode HTTP/1.1 }, parameters { gcode=M98 P"0:/macros/test-bufferoverflow4.g" }<\n>
Sending JSON reply, length 12<\n>
HTTP connection accepted<\n>
Sending reply, file = no<\n>
HTTP req, command words { GET /rr_reply HTTP/1.1 }, parameters { }<\n>
Sending G-Code reply to HTTP client 3 of 5 (length 5065)<\n>
Ran out of output buffers at ../src/Networking/HttpResponder.cpp(1543)<\n>
Sending JSON reply, length 2915<\n>
HTTP connection accepted<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { flags=d99fn }<\n>
HTTP connection accepted<\n>
Sending JSON reply, length 2915<\n>
HTTP req, command words { GET /rr_reply HTTP/1.1 }, parameters { }<\n>
Sending reply, file = no<\n>
HTTP connection accepted<\n>
Sending G-Code reply to HTTP client 1 of 5 (length 844)<\n>
HTTP connection accepted<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { flags=d99fn }<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key=inputs flags=d99vn }<\n>
Ran out of output buffers at ../src/Networking/HttpResponder.cpp(1112)<\n>
HTTP connection accepted<\n>
HTTP req, command words { GET /rr_reply HTTP/1.1 }, parameters { }<\n>
Sending reply, file = no<\n>
Sending G-Code reply to HTTP client 1 of 5 (length 4432)<\n>
HTTP connection accepted<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key=inputs flags=d99vn }<\n>
Ran out of output buffers at ../src/Networking/HttpResponder.cpp(1112)<\n>
HTTP connection accepted<\n>
HTTP req, command words { GET /rr_reply HTTP/1.1 }, parameters { }<\n>
Sending reply, file = no<\n>
Sending G-Code reply to HTTP client 2 of 5 (length 4432)<\n>
Ran out of output buffers at ../src/Networking/HttpResponder.cpp(1112)<\n>
HTTP connection accepted<\n>
Sending reply, file = no<\n>
HTTP req, command words { GET /rr_reply HTTP/1.1 }, parameters { }<\n>
Sending G-Code reply to HTTP client 3 of 5 (length 4432)<\n>
HTTP connection accepted<\n>
HTTP req, command words { GET /rr_reply HTTP/1.1 }, parameters { }<\n>
Sending reply, file = no<\n>
Sending G-Code reply to HTTP client 4 of 5 (length 4432)<\n>
HTTP connection accepted<\n>
Sending reply, file = no<\n>
HTTP req, command words { GET /rr_reply HTTP/1.1 }, parameters { }<\n>
Sending G-Code reply to HTTP client 5 of 5 (length 4432)<\n>
Sending JSON reply, length 3119<\n>
HTTP connection accepted<\n>
HTTP req, command words { GET /rr_reply HTTP/1.1 }, parameters { }<\n>
Sending reply, file = no<\n>
HTTP connection accepted<\n>
Sending JSON reply, length 2915<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key= flags=fvnd99a0 }<\n>
HTTP connection accepted<\n>
Sending reply, file = no<\n>
HTTP req, command words { GET /rr_reply HTTP/1.1 }, parameters { }<\n>
HTTP connection accepted<\n>
Sending JSON reply, length 3123<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key=inputs flags=vnd2a0 }<\n>
HTTP connection accepted<\n>
Sending JSON reply, length 65<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key=inputs flags=vnd2a12 }<\n>
HTTP connection accepted<\n>
Sending JSON reply, length 312<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key=volumes flags=vnd2a0 }<\n>
HTTP connection accepted<\n>
Sending reply, file = no<\n>
HTTP req, command words { GET /rr_reply HTTP/1.1 }, parameters { }<\n>
HTTP connection accepted<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key=inputs flags=d99vna12 }<\n>
Sending JSON reply, length 66<\n>
HTTP connection accepted<\n>
HTTP req, command words { GET /rr_reply HTTP/1.1 }, parameters { }<\n>
Sending reply, file = no<\n>
HTTP connection accepted<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key=inputs flags=d99vn }<\n>
Sending JSON reply, length 3119<\n>
HTTP connection accepted<\n>
Sending JSON reply, length 308<\n>
HTTP connection accepted<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key=volumes flags=d99vn }<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { flags=d99fn }<\n>
Sending JSON reply, length 2914<\n>
HTTP connection accepted<\n>
Sending reply, file = no<\n>
HTTP req, command words { GET /rr_reply HTTP/1.1 }, parameters { }<\n>
HTTP connection accepted<\n>
Sending JSON reply, length 66<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key=inputs flags=d99vna12 }<\n>
HTTP connection accepted<\n>
Sending JSON reply, length 3119<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key=inputs flags=d99vn }<\n>
HTTP connection accepted<\n>
Sending JSON reply, length 12<\n>
HTTP req, command words { GET /rr_gcode HTTP/1.1 }, parameters { gcode=M98 P"0:/macros/test-bufferoverflow4.g" }<\n>
HTTP connection accepted<\n>
Sending JSON reply, length 308<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key=volumes flags=d99vn }<\n>
HTTP connection accepted<\n>
HTTP connection accepted<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key=inputs flags=d99vna12 }<\n>
Sending reply, file = no<\n>
HTTP req, command words { GET /rr_reply HTTP/1.1 }, parameters { }<\n>
Sending G-Code reply to HTTP client 1 of 5 (length 1688)<\n>
HTTP connection accepted<\n>
Sending JSON reply, length 12<\n>
HTTP req, command words { GET /rr_gcode HTTP/1.1 }, parameters { gcode=M98 P"0:/macros/test-bufferoverflow4.g" }<\n>
HTTP connection accepted<\n>
HTTP connection accepted<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key= flags=fvnd99a0 }<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { flags=d99fn }<\n>
Ran out of output buffers at ../src/Networking/HttpResponder.cpp(1543)<\n>
Sending JSON reply, length 2912<\n>
Sending JSON reply, length 66<\n>
Sending JSON reply, length 2918<\n>
HTTP connection accepted<\n>
Sending reply, file = no<\n>
HTTP req, command words { GET /rr_reply HTTP/1.1 }, parameters { }<\n>
Sending G-Code reply to HTTP client 1 of 5 (length 1266)<\n>
HTTP connection accepted<\n>
HTTP connection accepted<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key=inputs flags=vnd2a0 }<\n>
HTTP req, command words { GET /rr_model HTTP/1.1 }, parameters { key=inputs flags=d99vn }<\n>
HTTP connection accepted<\n>