Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e0ebc43

Browse files
committed
1 parent 131bc6c commit e0ebc43

File tree

2 files changed

+75
-2
lines changed

2 files changed

+75
-2
lines changed

‎httplib.h

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND 5
1919
#endif
2020

21+
#ifndef CPPHTTPLIB_KEEPALIVE_TIMEOUT_CHECK_INTERVAL_USECOND
22+
#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_CHECK_INTERVAL_USECOND 10000
23+
#endif
24+
2125
#ifndef CPPHTTPLIB_KEEPALIVE_MAX_COUNT
2226
#define CPPHTTPLIB_KEEPALIVE_MAX_COUNT 100
2327
#endif
@@ -3251,6 +3255,41 @@ class SSLSocketStream final : public Stream {
32513255
};
32523256
#endif
32533257

3258+
inline bool keep_alive(const std::atomic<socket_t> &svr_sock, socket_t sock,
3259+
time_t keep_alive_timeout_sec) {
3260+
using namespace std::chrono;
3261+
3262+
const auto interval_usec =
3263+
CPPHTTPLIB_KEEPALIVE_TIMEOUT_CHECK_INTERVAL_USECOND;
3264+
3265+
// Avoid expensive `steady_clock::now()` call for the first time
3266+
if (select_read(sock, 0, interval_usec) > 0) { return true; }
3267+
3268+
const auto start = steady_clock::now() - microseconds{interval_usec};
3269+
const auto timeout = seconds{keep_alive_timeout_sec};
3270+
3271+
while (true) {
3272+
if (svr_sock == INVALID_SOCKET) {
3273+
break; // Server socket is closed
3274+
}
3275+
3276+
auto val = select_read(sock, 0, interval_usec);
3277+
if (val < 0) {
3278+
break; // Ssocket error
3279+
} else if (val == 0) {
3280+
if (steady_clock::now() - start > timeout) {
3281+
break; // Timeout
3282+
}
3283+
} else {
3284+
return true; // Ready for read
3285+
}
3286+
3287+
std::this_thread::sleep_for(microseconds{interval_usec});
3288+
}
3289+
3290+
return false;
3291+
}
3292+
32543293
template <typename T>
32553294
inline bool
32563295
process_server_socket_core(const std::atomic<socket_t> &svr_sock, socket_t sock,
@@ -3259,8 +3298,7 @@ process_server_socket_core(const std::atomic<socket_t> &svr_sock, socket_t sock,
32593298
assert(keep_alive_max_count > 0);
32603299
auto ret = false;
32613300
auto count = keep_alive_max_count;
3262-
while (svr_sock != INVALID_SOCKET && count > 0 &&
3263-
select_read(sock, keep_alive_timeout_sec, 0) > 0) {
3301+
while (count > 0 && keep_alive(svr_sock, sock, keep_alive_timeout_sec)) {
32643302
auto close_connection = count == 1;
32653303
auto connection_closed = false;
32663304
ret = callback(close_connection, connection_closed);

‎test/test.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5268,6 +5268,41 @@ TEST(KeepAliveTest, Issue1041) {
52685268
EXPECT_EQ(StatusCode::OK_200, result->status);
52695269
}
52705270

5271+
TEST(KeepAliveTest, Issue1959) {
5272+
Server svr;
5273+
svr.set_keep_alive_timeout(5);
5274+
5275+
svr.Get("/a", [&](const Request & /*req*/, Response &res) {
5276+
res.set_content("a", "text/plain");
5277+
});
5278+
5279+
auto listen_thread = std::thread([&svr]() { svr.listen("localhost", PORT); });
5280+
auto se = detail::scope_exit([&] {
5281+
if (!svr.is_running()) return;
5282+
svr.stop();
5283+
listen_thread.join();
5284+
ASSERT_FALSE(svr.is_running());
5285+
});
5286+
5287+
svr.wait_until_ready();
5288+
5289+
Client cli("localhost", PORT);
5290+
cli.set_keep_alive(true);
5291+
5292+
using namespace std::chrono;
5293+
auto start = steady_clock::now();
5294+
5295+
cli.Get("/a");
5296+
5297+
svr.stop();
5298+
listen_thread.join();
5299+
5300+
auto end = steady_clock::now();
5301+
auto elapsed = duration_cast<milliseconds>(end - start).count();
5302+
5303+
EXPECT_LT(elapsed, 5000);
5304+
}
5305+
52715306
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
52725307
TEST(KeepAliveTest, SSLClientReconnection) {
52735308
SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /