From 438319cfcbf23eac816f7926b1b341cc6034cedc Mon Sep 17 00:00:00 2001 From: yhirose Date: Sat, 3 Oct 2026 17:47:30 -0400 Subject: [PATCH] Fix WebSocket pings being sent early on spurious wakeups The heartbeat thread waited on ping_cv_ without a predicate, so a spurious wakeup ended the wait early and sent a ping before ping_interval_sec_ had elapsed. With max_missed_pongs enabled, the early ping also counted toward the pong timeout. Pass a predicate to wait_for so that the wait only ends when the interval elapses or the connection is closed. Reported in #2612. --- httplib.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/httplib.h b/httplib.h index 34cff001..f9a76c5d 100644 --- a/httplib.h +++ b/httplib.h @@ -22828,7 +22828,9 @@ inline void WebSocket::start_heartbeat() { ping_thread_ = std::thread([this]() { std::unique_lock lock(ping_mutex_); while (!closed_) { - ping_cv_.wait_for(lock, std::chrono::seconds(ping_interval_sec_)); + // The predicate keeps a spurious wakeup from sending a ping early + ping_cv_.wait_for(lock, std::chrono::seconds(ping_interval_sec_), + [this]() { return closed_.load(); }); if (closed_) { break; } // If the peer has failed to respond to the previous pings, give up. // RFC 6455 does not define a pong-timeout mechanism; this is an