Skip to content

Commit 1550cf6

Browse files
committed
fix: prevent write_response_core crashes on Android
This fixes crashes in httplib::Server::write_response_core that occur when writing HTTP responses to clients on Android devices. The crash was caused by socket state issues when clients disconnect during response transmission or when connections become invalid. Root causes: 1. Long-lived keep-alive connections: Connections could stay open indefinitely, increasing the chance of write failures when the client disconnects unexpectedly 2. Socket buffering issues: Nagle's algorithm could delay small writes, causing timeouts or connection issues 3. Slow connection cleanup: Idle connections weren't being closed promptly, leading to stale socket state 4. Empty error responses: Some error responses had no body, which could cause issues in write_response_core Fixes: 1. Connection limiting: - set_keep_alive_max_count(10): Limits requests per connection to prevent indefinitely long-lived connections - set_keep_alive_timeout(5s): Closes idle connections promptly to avoid stale socket state - set_idle_interval(1s): Improves connection cleanup on Android 2. Socket configuration: - set_tcp_nodelay(true): Disables Nagle's algorithm to avoid buffering delays during response writes, reducing the window for client disconnects during transmission 3. Error handling: - set_error_handler(): Ensures all error responses have content and logs errors for debugging. Empty response bodies could cause issues in write_response_core. These settings reduce the likelihood of writing to invalid/closed sockets, which was causing the SIGSEGV crashes in write_response_core on Android devices. Backtrace showed crash at: httplib::Server::write_response_core -> Socket write operations
1 parent 3e306b1 commit 1550cf6

1 file changed

Lines changed: 25 additions & 0 deletions

File tree

src/odr/http_server.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,18 @@ class HttpServer::Impl {
2828
// Write timeout: 60 seconds (allows time for large document transfers)
2929
m_server->set_write_timeout(60, 0);
3030

31+
// Connection management to prevent write_response_core crashes.
32+
// These settings prevent crashes when clients disconnect during response
33+
// transmission or when sockets become invalid.
34+
// Limit keep-alive requests per connection (prevents long-lived connections)
35+
m_server->set_keep_alive_max_count(10);
36+
// Keep-alive timeout: 5 seconds (closes idle connections promptly)
37+
m_server->set_keep_alive_timeout(5, 0);
38+
// Idle interval: 1 second (improves connection cleanup on Android)
39+
m_server->set_idle_interval(1, 0);
40+
// Enable TCP_NODELAY to avoid buffering issues during response writes
41+
m_server->set_tcp_nodelay(true);
42+
3143
// Set up exception handler to catch any internal httplib exceptions.
3244
// This prevents crashes when exceptions occur during request processing.
3345
m_server->set_exception_handler([this](const httplib::Request & /*req*/,
@@ -46,6 +58,19 @@ class HttpServer::Impl {
4658
res.set_content("Internal Server Error", "text/plain");
4759
});
4860

61+
// Set up error handler to customize error responses.
62+
// This helps provide consistent error responses and logs errors that occur
63+
// during request processing, including socket write errors.
64+
m_server->set_error_handler([this](const httplib::Request &req,
65+
httplib::Response &res) {
66+
ODR_ERROR(*m_logger, "HTTP error " << res.status << " for path: "
67+
<< req.path);
68+
// Ensure error responses have content to avoid write_response_core issues
69+
if (res.body.empty()) {
70+
res.set_content("Error " + std::to_string(res.status), "text/plain");
71+
}
72+
});
73+
4974
m_server->Get("/",
5075
[](const httplib::Request & /*req*/, httplib::Response &res) {
5176
res.set_content("Hello World!", "text/plain");

0 commit comments

Comments
 (0)