Skip to content

Commit 9c91b6f

Browse files
committed
Fix #1645
1 parent cee838e commit 9c91b6f

File tree

2 files changed

+64
-9
lines changed

2 files changed

+64
-9
lines changed

httplib.h

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,7 @@ class Server {
932932
bool is_running() const;
933933
void wait_until_ready() const;
934934
void stop();
935+
void decommission();
935936

936937
std::function<TaskQueue *(void)> new_task_queue;
937938

@@ -1006,7 +1007,7 @@ class Server {
10061007
virtual bool process_and_close_socket(socket_t sock);
10071008

10081009
std::atomic<bool> is_running_{false};
1009-
std::atomic<bool> done_{false};
1010+
std::atomic<bool> is_decommisioned{false};
10101011

10111012
struct MountPointEntry {
10121013
std::string mount_point;
@@ -6111,27 +6112,27 @@ inline Server &Server::set_payload_max_length(size_t length) {
61116112

61126113
inline bool Server::bind_to_port(const std::string &host, int port,
61136114
int socket_flags) {
6114-
return bind_internal(host, port, socket_flags) >= 0;
6115+
auto ret = bind_internal(host, port, socket_flags);
6116+
if (ret == -1) { is_decommisioned = true; }
6117+
return ret >= 0;
61156118
}
61166119
inline int Server::bind_to_any_port(const std::string &host, int socket_flags) {
6117-
return bind_internal(host, 0, socket_flags);
6120+
auto ret = bind_internal(host, 0, socket_flags);
6121+
if (ret == -1) { is_decommisioned = true; }
6122+
return ret;
61186123
}
61196124

6120-
inline bool Server::listen_after_bind() {
6121-
auto se = detail::scope_exit([&]() { done_ = true; });
6122-
return listen_internal();
6123-
}
6125+
inline bool Server::listen_after_bind() { return listen_internal(); }
61246126

61256127
inline bool Server::listen(const std::string &host, int port,
61266128
int socket_flags) {
6127-
auto se = detail::scope_exit([&]() { done_ = true; });
61286129
return bind_to_port(host, port, socket_flags) && listen_internal();
61296130
}
61306131

61316132
inline bool Server::is_running() const { return is_running_; }
61326133

61336134
inline void Server::wait_until_ready() const {
6134-
while (!is_running() && !done_) {
6135+
while (!is_running_ && !is_decommisioned) {
61356136
std::this_thread::sleep_for(std::chrono::milliseconds{1});
61366137
}
61376138
}
@@ -6143,8 +6144,11 @@ inline void Server::stop() {
61436144
detail::shutdown_socket(sock);
61446145
detail::close_socket(sock);
61456146
}
6147+
is_decommisioned = false;
61466148
}
61476149

6150+
inline void Server::decommission() { is_decommisioned = true; }
6151+
61486152
inline bool Server::parse_request_line(const char *s, Request &req) const {
61496153
auto len = strlen(s);
61506154
if (len < 2 || s[len - 2] != '\r' || s[len - 1] != '\n') { return false; }
@@ -6499,6 +6503,8 @@ Server::create_server_socket(const std::string &host, int port,
64996503

65006504
inline int Server::bind_internal(const std::string &host, int port,
65016505
int socket_flags) {
6506+
if (is_decommisioned) { return -1; }
6507+
65026508
if (!is_valid()) { return -1; }
65036509

65046510
svr_sock_ = create_server_socket(host, port, socket_flags, socket_options_);
@@ -6524,6 +6530,8 @@ inline int Server::bind_internal(const std::string &host, int port,
65246530
}
65256531

65266532
inline bool Server::listen_internal() {
6533+
if (is_decommisioned) { return false; }
6534+
65276535
auto ret = true;
65286536
is_running_ = true;
65296537
auto se = detail::scope_exit([&]() { is_running_ = false; });
@@ -6613,6 +6621,7 @@ inline bool Server::listen_internal() {
66136621
task_queue->shutdown();
66146622
}
66156623

6624+
is_decommisioned = !ret;
66166625
return ret;
66176626
}
66186627

test/test.cc

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4926,6 +4926,52 @@ TEST(ServerStopTest, ListenFailure) {
49264926
t.join();
49274927
}
49284928

4929+
TEST(ServerStopTest, Decommision) {
4930+
Server svr;
4931+
4932+
svr.Get("/hi", [&](const Request &, Response &res) { res.body = "hi..."; });
4933+
4934+
for (int i = 0; i < 4; i++) {
4935+
auto is_even = !(i % 2);
4936+
4937+
std::thread t{[&] {
4938+
try {
4939+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
4940+
4941+
if (is_even) {
4942+
throw std::runtime_error("Some thing that happens to go wrong.");
4943+
}
4944+
4945+
svr.listen(HOST, PORT);
4946+
} catch (...) { svr.decommission(); }
4947+
}};
4948+
4949+
svr.wait_until_ready();
4950+
4951+
// Server is up
4952+
{
4953+
Client cli(HOST, PORT);
4954+
auto res = cli.Get("/hi");
4955+
if (is_even) {
4956+
EXPECT_FALSE(res);
4957+
} else {
4958+
EXPECT_TRUE(res);
4959+
EXPECT_EQ("hi...", res->body);
4960+
}
4961+
}
4962+
4963+
svr.stop();
4964+
t.join();
4965+
4966+
// Server is down...
4967+
{
4968+
Client cli(HOST, PORT);
4969+
auto res = cli.Get("/hi");
4970+
EXPECT_FALSE(res);
4971+
}
4972+
}
4973+
}
4974+
49294975
TEST(StreamingTest, NoContentLengthStreaming) {
49304976
Server svr;
49314977

0 commit comments

Comments
 (0)