Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions include/crow/http_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
#endif

#include <atomic>
#include <cerrno>
#include <chrono>
#include <cstdint>
#include <cstring>
#include <future>
#include <memory>
#include <thread>
Expand Down Expand Up @@ -46,7 +48,7 @@ namespace crow // NOTE: Already documented in "crow/app.h"
{
public:
Server(Handler* handler,
typename Acceptor::endpoint endpoint,
typename Acceptor::endpoint endpoint,
std::string server_name = std::string("Crow/") + VERSION,
std::tuple<Middlewares...>* middlewares = nullptr,
unsigned int concurrency = 1,
Expand Down Expand Up @@ -77,6 +79,12 @@ namespace crow // NOTE: Already documented in "crow/app.h"
return;
}

if(set_cloexec(acceptor_.raw_acceptor().native_handle()) == -1){
CROW_LOG_ERROR << "Failed to set FD_CLOEXEC on start: " << std::strerror(errno);
startup_failed_ = true;
return;
}

acceptor_.raw_acceptor().set_option(Acceptor::reuse_address_option(), ec);
if (ec) {
CROW_LOG_ERROR << "Failed to set socket option: " << ec.message();
Expand Down Expand Up @@ -202,8 +210,8 @@ namespace crow // NOTE: Already documented in "crow/app.h"
}
handler_->port(acceptor_.port());
handler_->address_is_bound();
CROW_LOG_INFO << server_name_
<< " server is running at " << acceptor_.url_display(handler_->ssl_used())
CROW_LOG_INFO << server_name_
<< " server is running at " << acceptor_.url_display(handler_->ssl_used())
<< " using " << concurrency_ << " threads";
CROW_LOG_INFO << "Call `app.loglevel(crow::LogLevel::Warning)` to hide Info level logs.";

Expand Down Expand Up @@ -257,7 +265,7 @@ namespace crow // NOTE: Already documented in "crow/app.h"
io_context_.stop(); // Close main io_service
}


uint16_t port() const {
return acceptor_.local_endpoint().port();
}
Expand Down Expand Up @@ -310,14 +318,18 @@ namespace crow // NOTE: Already documented in "crow/app.h"
auto p = std::make_shared<Connection<Adaptor, Handler, Middlewares...>>(
ic, handler_, server_name_, middlewares_,
get_cached_date_str_pool_[context_idx], *task_timer_pool_[context_idx], adaptor_ctx_, task_queue_length_pool_[context_idx]);

CROW_LOG_DEBUG << &ic << " {" << context_idx << "} queue length: " << task_queue_length_pool_[context_idx];

acceptor_.raw_acceptor().async_accept(
p->socket(),
[this, p, &ic](error_code ec) {
if (!ec)
{
if(set_cloexec(p->socket().native_handle()) == -1){
CROW_LOG_ERROR << "Failed to set FD_CLOEXEC on accepted socket: " << std::strerror(errno);
}

asio::post(ic,
[p] {
p->start();
Expand Down
21 changes: 21 additions & 0 deletions include/crow/socket_acceptors.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#pragma once
#ifndef _WIN32
#include <fcntl.h>
#endif
#ifdef CROW_USE_BOOST
#include <boost/asio.hpp>
#ifdef CROW_ENABLE_SSL
Expand All @@ -18,6 +21,24 @@

namespace crow
{
/// Set FD_CLOEXEC on a native socket handle to prevent file descriptor leaking across fork/exec.
template<typename NativeHandle>
inline int set_cloexec([[maybe_unused]] NativeHandle fd)
{
#ifndef _WIN32
int flags = fcntl(fd, F_GETFD);
if (flags != -1)
{
return fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
}
// Retrieving current flags failed
return flags;
#else
// Return not -1 (following fcntl()'s docs)
return 0;
#endif
}

#ifdef CROW_USE_BOOST
namespace asio = boost::asio;
using error_code = boost::system::error_code;
Expand Down
Loading