Bug #11301 » 0002-WT-11302-avoid-use-after-free-with-closed-listeners.patch
src/http/Server.C | ||
---|---|---|
const std::string &address,
|
||
Wt::AsioWrapper::error_code &errc)
|
||
{
|
||
tcp_listeners_.push_back(TcpListener(asio::ip::tcp::acceptor(wt_.ioService()), TcpConnectionPtr()));
|
||
asio::ip::tcp::acceptor &tcp_acceptor = tcp_listeners_.back().acceptor;
|
||
tcp_listeners_.push_back(std::make_shared<TcpListener>(asio::ip::tcp::acceptor(wt_.ioService()), TcpConnectionPtr()));
|
||
asio::ip::tcp::acceptor &tcp_acceptor = tcp_listeners_.back()->acceptor;
|
||
tcp_acceptor.open(endpoint.protocol());
|
||
tcp_acceptor.set_option(asio::ip::tcp::acceptor::reuse_address(true));
|
||
#ifndef WT_WIN32
|
||
... | ... | |
LOG_INFO_S(&wt_, "started server: " << addressString("http", endpoint, address));
|
||
tcp_listeners_.back().new_connection.reset
|
||
tcp_listeners_.back()->new_connection.reset
|
||
(new TcpConnection(wt_.ioService(), this, connection_manager_,
|
||
request_handler_));
|
||
} else {
|
||
... | ... | |
const std::string &address,
|
||
Wt::AsioWrapper::error_code &errc)
|
||
{
|
||
ssl_listeners_.push_back(SslListener(asio::ip::tcp::acceptor(wt_.ioService()), SslConnectionPtr()));
|
||
asio::ip::tcp::acceptor &ssl_acceptor = ssl_listeners_.back().acceptor;
|
||
ssl_listeners_.push_back(std::make_shared<SslListener>(asio::ip::tcp::acceptor(wt_.ioService()), SslConnectionPtr()));
|
||
asio::ip::tcp::acceptor &ssl_acceptor = ssl_listeners_.back()->acceptor;
|
||
ssl_acceptor.open(endpoint.protocol());
|
||
ssl_acceptor.set_option(asio::ip::tcp::acceptor::reuse_address(true));
|
||
#ifndef WT_WIN32
|
||
... | ... | |
LOG_INFO_S(&wt_, "started server: " << addressString("https", endpoint, address));
|
||
ssl_listeners_.back().new_connection.reset
|
||
ssl_listeners_.back()->new_connection.reset
|
||
(new SslConnection(wt_.ioService(), this, ssl_context_, connection_manager_,
|
||
request_handler_));
|
||
} else {
|
||
... | ... | |
if (ssl_listeners_.empty())
|
||
return -1;
|
||
else
|
||
return ssl_listeners_.front().acceptor.local_endpoint().port();
|
||
return ssl_listeners_.front()->acceptor.local_endpoint().port();
|
||
#else // HTTP_WITH_SSL
|
||
return -1;
|
||
#endif // HTTP_WITH_SSL
|
||
}
|
||
return tcp_listeners_.front().acceptor.local_endpoint().port();
|
||
return tcp_listeners_.front()->acceptor.local_endpoint().port();
|
||
}
|
||
void Server::startAccept()
|
||
... | ... | |
* need to access the ConnectionManager mutex in any case).
|
||
*/
|
||
for (std::size_t i = 0; i < tcp_listeners_.size(); ++i) {
|
||
asio::ip::tcp::acceptor &acceptor = tcp_listeners_[i].acceptor;
|
||
TcpConnectionPtr &new_connection = tcp_listeners_[i].new_connection;
|
||
asio::ip::tcp::acceptor &acceptor = tcp_listeners_[i]->acceptor;
|
||
TcpConnectionPtr &new_connection = tcp_listeners_[i]->new_connection;
|
||
acceptor.async_accept(new_connection->socket(),
|
||
accept_strand_.wrap(
|
||
std::bind(&Server::handleTcpAccept, this,
|
||
&tcp_listeners_[i],
|
||
tcp_listeners_[i],
|
||
std::placeholders::_1)));
|
||
}
|
||
#ifdef HTTP_WITH_SSL
|
||
for (std::size_t i = 0; i < ssl_listeners_.size(); ++i) {
|
||
asio::ip::tcp::acceptor &acceptor = ssl_listeners_[i].acceptor;
|
||
SslConnectionPtr &new_connection = ssl_listeners_[i].new_connection;
|
||
asio::ip::tcp::acceptor &acceptor = ssl_listeners_[i]->acceptor;
|
||
SslConnectionPtr &new_connection = ssl_listeners_[i]->new_connection;
|
||
acceptor.async_accept(new_connection->socket(),
|
||
accept_strand_.wrap(
|
||
std::bind(&Server::handleSslAccept, this,
|
||
&ssl_listeners_[i],
|
||
ssl_listeners_[i],
|
||
std::placeholders::_1)));
|
||
}
|
||
#endif // HTTP_WITH_SSL
|
||
... | ... | |
if (!err) {
|
||
// tcp_listeners_.front() should be fine here:
|
||
// it should be the only acceptor when this is a session process
|
||
auto port = tcp_listeners_.front().acceptor.local_endpoint().port();
|
||
auto port = tcp_listeners_.front()->acceptor.local_endpoint().port();
|
||
Wt::WStringStream ss;
|
||
ss << "port:" << port << "\n";
|
||
auto buf = std::make_shared<std::string>(ss.str());
|
||
... | ... | |
void Server::handleResume()
|
||
{
|
||
for (std::size_t i = 0; i < tcp_listeners_.size(); ++i)
|
||
tcp_listeners_[i].acceptor.close();
|
||
tcp_listeners_[i]->acceptor.close();
|
||
tcp_listeners_.clear();
|
||
#ifdef HTTP_WITH_SSL
|
||
for (std::size_t i = 0; i < ssl_listeners_.size(); ++i)
|
||
ssl_listeners_[i].acceptor.close();
|
||
ssl_listeners_[i]->acceptor.close();
|
||
ssl_listeners_.clear();
|
||
#endif // HTTP_WITH_SSL
|
||
start();
|
||
}
|
||
void Server::handleTcpAccept(TcpListener *listener, const Wt::AsioWrapper::error_code& e)
|
||
void Server::handleTcpAccept(const std::weak_ptr<TcpListener>& listener,
|
||
const Wt::AsioWrapper::error_code& e)
|
||
{
|
||
if (!e) {
|
||
connection_manager_.start(listener->new_connection);
|
||
listener->new_connection.reset(new TcpConnection(wt_.ioService(), this,
|
||
connection_manager_, request_handler_));
|
||
} else if (!listener->acceptor.is_open()) {
|
||
auto l = listener.lock();
|
||
if (!l || (e && !l->acceptor.is_open())) {
|
||
// server shutdown
|
||
LOG_DEBUG("handleTcpAccept: async_accept error (acceptor closed, probably server shutdown): " << e.message());
|
||
LOG_DEBUG("handleTcpAccept: async_accept error (no listener, probably server shutdown): " << e.message());
|
||
return;
|
||
}
|
||
if (!e) {
|
||
connection_manager_.start(l->new_connection);
|
||
l->new_connection.reset(new TcpConnection(wt_.ioService(), this,
|
||
connection_manager_, request_handler_));
|
||
} else {
|
||
LOG_ERROR("handleTcpAccept: async_accept error: " << e.message());
|
||
}
|
||
listener->acceptor.async_accept(listener->new_connection->socket(),
|
||
accept_strand_.wrap(
|
||
std::bind(&Server::handleTcpAccept, this,
|
||
listener, std::placeholders::_1)));
|
||
l->acceptor.async_accept(l->new_connection->socket(),
|
||
accept_strand_.wrap(
|
||
std::bind(&Server::handleTcpAccept, this,
|
||
listener, std::placeholders::_1)));
|
||
}
|
||
#ifdef HTTP_WITH_SSL
|
||
void Server::handleSslAccept(SslListener *listener, const Wt::AsioWrapper::error_code& e)
|
||
void Server::handleSslAccept(const std::weak_ptr<SslListener>& listener,
|
||
const Wt::AsioWrapper::error_code& e)
|
||
{
|
||
if (!e) {
|
||
connection_manager_.start(listener->new_connection);
|
||
listener->new_connection.reset(new SslConnection(wt_.ioService(), this,
|
||
ssl_context_, connection_manager_, request_handler_));
|
||
} else if (!listener->acceptor.is_open()) {
|
||
auto l = listener.lock();
|
||
if (!l || (e && !l->acceptor.is_open())) {
|
||
// server shutdown
|
||
LOG_DEBUG("handleSslAccept: async_accept error (acceptor closed, probably server shutdown): " << e.message());
|
||
LOG_DEBUG("handleSslAccept: async_accept error (no listener, probably server shutdown): " << e.message());
|
||
return;
|
||
}
|
||
if (!e) {
|
||
connection_manager_.start(l->new_connection);
|
||
l->new_connection.reset(new SslConnection(wt_.ioService(), this,
|
||
ssl_context_, connection_manager_, request_handler_));
|
||
} else {
|
||
LOG_ERROR("handleSslAccept: async_accept error: " << e.message());
|
||
}
|
||
listener->acceptor.async_accept(listener->new_connection->socket(),
|
||
accept_strand_.wrap(
|
||
std::bind(&Server::handleSslAccept, this,
|
||
listener, std::placeholders::_1)));
|
||
l->acceptor.async_accept(l->new_connection->socket(),
|
||
accept_strand_.wrap(
|
||
std::bind(&Server::handleSslAccept, this,
|
||
listener, std::placeholders::_1)));
|
||
}
|
||
#endif // HTTP_WITH_SSL
|
||
... | ... | |
// operations. Once all operations have finished the io_service::run() call
|
||
// will exit.
|
||
for (std::size_t i = 0; i < tcp_listeners_.size(); ++i)
|
||
tcp_listeners_[i].acceptor.close();
|
||
tcp_listeners_[i]->acceptor.close();
|
||
tcp_listeners_.clear();
|
||
#ifdef HTTP_WITH_SSL
|
||
for (std::size_t i = 0; i < ssl_listeners_.size(); ++i)
|
||
ssl_listeners_[i].acceptor.close();
|
||
ssl_listeners_[i]->acceptor.close();
|
||
ssl_listeners_.clear();
|
||
#endif // HTTP_WITH_SSL
|
||
src/http/Server.h | ||
---|---|---|
#include "Wt/WLogger.h"
|
||
#include <memory>
|
||
namespace http {
|
||
namespace server {
|
||
... | ... | |
void closeParentConnection();
|
||
/// Handle completion of an asynchronous accept operation.
|
||
void handleTcpAccept(TcpListener *listener, const Wt::AsioWrapper::error_code& e);
|
||
void handleTcpAccept(const std::weak_ptr<TcpListener>& listener,
|
||
const Wt::AsioWrapper::error_code& e);
|
||
/// Handle a request to stop the server.
|
||
void handleStop();
|
||
... | ... | |
Wt::AsioWrapper::strand accept_strand_;
|
||
/// Acceptors used to listen for incoming http connections.
|
||
std::vector<TcpListener> tcp_listeners_;
|
||
std::vector<std::shared_ptr<TcpListener>> tcp_listeners_;
|
||
#ifdef HTTP_WITH_SSL
|
||
struct SslListener {
|
||
... | ... | |
asio::ssl::context ssl_context_;
|
||
/// Acceptors used to listen for incoming https connections
|
||
std::vector<SslListener> ssl_listeners_;
|
||
std::vector<std::shared_ptr<SslListener>> ssl_listeners_;
|
||
/// Add new SSL listener, called from start()
|
||
void addSslListener(asio::ip::tcp::resolver &resolver,
|
||
... | ... | |
Wt::AsioWrapper::error_code &errc);
|
||
/// Handle completion of an asynchronous SSL accept operation.
|
||
void handleSslAccept(SslListener *listener, const Wt::AsioWrapper::error_code& e);
|
||
void handleSslAccept(const std::weak_ptr<SslListener>& listener,
|
||
const Wt::AsioWrapper::error_code& e);
|
||
#endif // HTTP_WITH_SSL
|
||
void handleTimeout(asio::steady_timer *timer,
|
- « Previous
- 1
- 2
- 3
- 4
- Next »