diff --git a/asio/src/examples/allocation/server.cpp b/asio/src/examples/allocation/server.cpp index d80784fd..7adc304a 100644 --- a/asio/src/examples/allocation/server.cpp +++ b/asio/src/examples/allocation/server.cpp @@ -199,11 +199,12 @@ public: if (!error) { new_session->start(); - new_session.reset(new session(io_service_)); - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, - asio::placeholders::error)); } + + new_session.reset(new session(io_service_)); + acceptor_.async_accept(new_session->socket(), + boost::bind(&server::handle_accept, this, new_session, + asio::placeholders::error)); } private: diff --git a/asio/src/examples/buffers/reference_counted.cpp b/asio/src/examples/buffers/reference_counted.cpp index 5a50124c..7649f96e 100644 --- a/asio/src/examples/buffers/reference_counted.cpp +++ b/asio/src/examples/buffers/reference_counted.cpp @@ -92,11 +92,12 @@ public: if (!error) { new_session->start(); - new_session.reset(new session(io_service_)); - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, - asio::placeholders::error)); } + + new_session.reset(new session(io_service_)); + acceptor_.async_accept(new_session->socket(), + boost::bind(&server::handle_accept, this, new_session, + asio::placeholders::error)); } private: diff --git a/asio/src/examples/chat/chat_server.cpp b/asio/src/examples/chat/chat_server.cpp index 9ae73125..97d32122 100644 --- a/asio/src/examples/chat/chat_server.cpp +++ b/asio/src/examples/chat/chat_server.cpp @@ -181,6 +181,11 @@ public: const tcp::endpoint& endpoint) : io_service_(io_service), acceptor_(io_service, endpoint) + { + start_accept(); + } + + void start_accept() { chat_session_ptr new_session(new chat_session(io_service_, room_)); acceptor_.async_accept(new_session->socket(), @@ -194,11 +199,9 @@ public: if (!error) { session->start(); - chat_session_ptr new_session(new chat_session(io_service_, room_)); - acceptor_.async_accept(new_session->socket(), - boost::bind(&chat_server::handle_accept, this, new_session, - asio::placeholders::error)); } + + start_accept(); } private: diff --git a/asio/src/examples/echo/async_tcp_echo_server.cpp b/asio/src/examples/echo/async_tcp_echo_server.cpp index dff511b0..1f710a9d 100644 --- a/asio/src/examples/echo/async_tcp_echo_server.cpp +++ b/asio/src/examples/echo/async_tcp_echo_server.cpp @@ -36,6 +36,7 @@ public: asio::placeholders::bytes_transferred)); } +private: void handle_read(const asio::error_code& error, size_t bytes_transferred) { @@ -67,7 +68,6 @@ public: } } -private: tcp::socket socket_; enum { max_length = 1024 }; char data_[max_length]; @@ -79,6 +79,12 @@ public: server(asio::io_service& io_service, short port) : io_service_(io_service), acceptor_(io_service, tcp::endpoint(tcp::v4(), port)) + { + start_accept(); + } + +private: + void start_accept() { session* new_session = new session(io_service_); acceptor_.async_accept(new_session->socket(), @@ -92,18 +98,15 @@ public: if (!error) { new_session->start(); - new_session = new session(io_service_); - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, - asio::placeholders::error)); } else { delete new_session; } + + start_accept(); } -private: asio::io_service& io_service_; tcp::acceptor acceptor_; }; diff --git a/asio/src/examples/fork/process_per_connection.cpp b/asio/src/examples/fork/process_per_connection.cpp index d8078d84..9f30a170 100644 --- a/asio/src/examples/fork/process_per_connection.cpp +++ b/asio/src/examples/fork/process_per_connection.cpp @@ -43,11 +43,16 @@ private: void handle_signal_wait() { - // Reap completed child processes so that we don't end up with zombies. - int status = 0; - while (waitpid(-1, &status, WNOHANG) > 0) {} + // Only the parent process should check for this signal. We can determine + // whether we are in the parent by checking if the acceptor is still open. + if (acceptor_.is_open()) + { + // Reap completed child processes so that we don't end up with zombies. + int status = 0; + while (waitpid(-1, &status, WNOHANG) > 0) {} - start_signal_wait(); + start_signal_wait(); + } } void start_accept() @@ -76,6 +81,9 @@ private: // acceptor. It remains open in the parent. acceptor_.close(); + // The child process is not interested in processing the SIGCHLD signal. + signal_.cancel(); + start_read(); } else @@ -93,6 +101,7 @@ private: else { std::cerr << "Accept error: " << ec.message() << std::endl; + start_accept(); } } diff --git a/asio/src/examples/http/server/server.cpp b/asio/src/examples/http/server/server.cpp index fc7c30b3..ecfbfa98 100644 --- a/asio/src/examples/http/server/server.cpp +++ b/asio/src/examples/http/server/server.cpp @@ -21,8 +21,7 @@ server::server(const std::string& address, const std::string& port, signals_(io_service_), acceptor_(io_service_), connection_manager_(), - new_connection_(new connection(io_service_, - connection_manager_, request_handler_)), + new_connection_(), request_handler_(doc_root) { // Register to handle the signals that indicate when the server should exit. @@ -43,9 +42,8 @@ server::server(const std::string& address, const std::string& port, acceptor_.set_option(asio::ip::tcp::acceptor::reuse_address(true)); acceptor_.bind(endpoint); acceptor_.listen(); - acceptor_.async_accept(new_connection_->socket(), - boost::bind(&server::handle_accept, this, - asio::placeholders::error)); + + start_accept(); } void server::run() @@ -57,17 +55,30 @@ void server::run() io_service_.run(); } +void server::start_accept() +{ + new_connection_.reset(new connection(io_service_, + connection_manager_, request_handler_)); + acceptor_.async_accept(new_connection_->socket(), + boost::bind(&server::handle_accept, this, + asio::placeholders::error)); +} + void server::handle_accept(const asio::error_code& e) { + // Check whether the server was stopped by a signal before this completion + // handler had a chance to run. + if (!acceptor_.is_open()) + { + return; + } + if (!e) { connection_manager_.start(new_connection_); - new_connection_.reset(new connection(io_service_, - connection_manager_, request_handler_)); - acceptor_.async_accept(new_connection_->socket(), - boost::bind(&server::handle_accept, this, - asio::placeholders::error)); } + + start_accept(); } void server::handle_stop() diff --git a/asio/src/examples/http/server/server.hpp b/asio/src/examples/http/server/server.hpp index 4049aaa4..2e42d2ec 100644 --- a/asio/src/examples/http/server/server.hpp +++ b/asio/src/examples/http/server/server.hpp @@ -35,6 +35,9 @@ public: void run(); private: + /// Initiate an asynchronous accept operation. + void start_accept(); + /// Handle completion of an asynchronous accept operation. void handle_accept(const asio::error_code& e); diff --git a/asio/src/examples/http/server2/server.cpp b/asio/src/examples/http/server2/server.cpp index 3c06f8ac..78eb0aa8 100644 --- a/asio/src/examples/http/server2/server.cpp +++ b/asio/src/examples/http/server2/server.cpp @@ -19,8 +19,7 @@ server::server(const std::string& address, const std::string& port, : io_service_pool_(io_service_pool_size), signals_(io_service_pool_.get_io_service()), acceptor_(io_service_pool_.get_io_service()), - new_connection_(new connection( - io_service_pool_.get_io_service(), request_handler_)), + new_connection_(), request_handler_(doc_root) { // Register to handle the signals that indicate when the server should exit. @@ -41,9 +40,8 @@ server::server(const std::string& address, const std::string& port, acceptor_.set_option(asio::ip::tcp::acceptor::reuse_address(true)); acceptor_.bind(endpoint); acceptor_.listen(); - acceptor_.async_accept(new_connection_->socket(), - boost::bind(&server::handle_accept, this, - asio::placeholders::error)); + + start_accept(); } void server::run() @@ -51,17 +49,23 @@ void server::run() io_service_pool_.run(); } +void server::start_accept() +{ + new_connection_.reset(new connection( + io_service_pool_.get_io_service(), request_handler_)); + acceptor_.async_accept(new_connection_->socket(), + boost::bind(&server::handle_accept, this, + asio::placeholders::error)); +} + void server::handle_accept(const asio::error_code& e) { if (!e) { new_connection_->start(); - new_connection_.reset(new connection( - io_service_pool_.get_io_service(), request_handler_)); - acceptor_.async_accept(new_connection_->socket(), - boost::bind(&server::handle_accept, this, - asio::placeholders::error)); } + + start_accept(); } void server::handle_stop() diff --git a/asio/src/examples/http/server2/server.hpp b/asio/src/examples/http/server2/server.hpp index 900c815a..76fed5fc 100644 --- a/asio/src/examples/http/server2/server.hpp +++ b/asio/src/examples/http/server2/server.hpp @@ -37,6 +37,9 @@ public: void run(); private: + /// Initiate an asynchronous accept operation. + void start_accept(); + /// Handle completion of an asynchronous accept operation. void handle_accept(const asio::error_code& e); diff --git a/asio/src/examples/http/server3/server.cpp b/asio/src/examples/http/server3/server.cpp index ff5ee097..874afadc 100644 --- a/asio/src/examples/http/server3/server.cpp +++ b/asio/src/examples/http/server3/server.cpp @@ -21,7 +21,7 @@ server::server(const std::string& address, const std::string& port, : thread_pool_size_(thread_pool_size), signals_(io_service_), acceptor_(io_service_), - new_connection_(new connection(io_service_, request_handler_)), + new_connection_(), request_handler_(doc_root) { // Register to handle the signals that indicate when the server should exit. @@ -42,9 +42,8 @@ server::server(const std::string& address, const std::string& port, acceptor_.set_option(asio::ip::tcp::acceptor::reuse_address(true)); acceptor_.bind(endpoint); acceptor_.listen(); - acceptor_.async_accept(new_connection_->socket(), - boost::bind(&server::handle_accept, this, - asio::placeholders::error)); + + start_accept(); } void server::run() @@ -63,16 +62,22 @@ void server::run() threads[i]->join(); } +void server::start_accept() +{ + new_connection_.reset(new connection(io_service_, request_handler_)); + acceptor_.async_accept(new_connection_->socket(), + boost::bind(&server::handle_accept, this, + asio::placeholders::error)); +} + void server::handle_accept(const asio::error_code& e) { if (!e) { new_connection_->start(); - new_connection_.reset(new connection(io_service_, request_handler_)); - acceptor_.async_accept(new_connection_->socket(), - boost::bind(&server::handle_accept, this, - asio::placeholders::error)); } + + start_accept(); } void server::handle_stop() diff --git a/asio/src/examples/http/server3/server.hpp b/asio/src/examples/http/server3/server.hpp index b218f269..bcb3f42e 100644 --- a/asio/src/examples/http/server3/server.hpp +++ b/asio/src/examples/http/server3/server.hpp @@ -36,6 +36,9 @@ public: void run(); private: + /// Initiate an asynchronous accept operation. + void start_accept(); + /// Handle completion of an asynchronous accept operation. void handle_accept(const asio::error_code& e); diff --git a/asio/src/examples/iostreams/daytime_server.cpp b/asio/src/examples/iostreams/daytime_server.cpp index ed31596d..3fd4a267 100644 --- a/asio/src/examples/iostreams/daytime_server.cpp +++ b/asio/src/examples/iostreams/daytime_server.cpp @@ -34,8 +34,12 @@ int main() for (;;) { tcp::iostream stream; - acceptor.accept(*stream.rdbuf()); - stream << make_daytime_string(); + asio::error_code ec; + acceptor.accept(*stream.rdbuf(), ec); + if (!ec) + { + stream << make_daytime_string(); + } } } catch (std::exception& e) diff --git a/asio/src/examples/nonblocking/third_party_lib.cpp b/asio/src/examples/nonblocking/third_party_lib.cpp index 2c9c162a..84188811 100644 --- a/asio/src/examples/nonblocking/third_party_lib.cpp +++ b/asio/src/examples/nonblocking/third_party_lib.cpp @@ -208,8 +208,9 @@ private: if (!error) { new_connection->start(); - start_accept(); } + + start_accept(); } tcp::acceptor acceptor_; diff --git a/asio/src/examples/porthopper/server.cpp b/asio/src/examples/porthopper/server.cpp index 13f25984..36d4acf2 100644 --- a/asio/src/examples/porthopper/server.cpp +++ b/asio/src/examples/porthopper/server.cpp @@ -56,13 +56,13 @@ public: asio::async_read(*socket, request->to_buffers(), boost::bind(&server::handle_control_request, this, asio::placeholders::error, socket, request)); - - // Start waiting for a new control connection. - tcp_socket_ptr new_socket(new tcp::socket(acceptor_.get_io_service())); - acceptor_.async_accept(*new_socket, - boost::bind(&server::handle_accept, this, - asio::placeholders::error, new_socket)); } + + // Start waiting for a new control connection. + tcp_socket_ptr new_socket(new tcp::socket(acceptor_.get_io_service())); + acceptor_.async_accept(*new_socket, + boost::bind(&server::handle_accept, this, + asio::placeholders::error, new_socket)); } // Handle a new control request. diff --git a/asio/src/examples/serialization/server.cpp b/asio/src/examples/serialization/server.cpp index 7d7de0c4..7b02be64 100644 --- a/asio/src/examples/serialization/server.cpp +++ b/asio/src/examples/serialization/server.cpp @@ -72,20 +72,13 @@ public: conn->async_write(stocks_, boost::bind(&server::handle_write, this, asio::placeholders::error, conn)); + } - // Start an accept operation for a new connection. - connection_ptr new_conn(new connection(acceptor_.get_io_service())); - acceptor_.async_accept(new_conn->socket(), - boost::bind(&server::handle_accept, this, - asio::placeholders::error, new_conn)); - } - else - { - // An error occurred. Log it and return. Since we are not starting a new - // accept operation the io_service will run out of work to do and the - // server will exit. - std::cerr << e.message() << std::endl; - } + // Start an accept operation for a new connection. + connection_ptr new_conn(new connection(acceptor_.get_io_service())); + acceptor_.async_accept(new_conn->socket(), + boost::bind(&server::handle_accept, this, + asio::placeholders::error, new_conn)); } /// Handle completion of a write operation. diff --git a/asio/src/examples/ssl/server.cpp b/asio/src/examples/ssl/server.cpp index b8a4c017..3a53c0cc 100644 --- a/asio/src/examples/ssl/server.cpp +++ b/asio/src/examples/ssl/server.cpp @@ -107,10 +107,7 @@ public: context_.use_private_key_file("server.pem", asio::ssl::context::pem); context_.use_tmp_dh_file("dh512.pem"); - session* new_session = new session(io_service_, context_); - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, - asio::placeholders::error)); + start_accept(); } std::string get_password() const @@ -118,21 +115,27 @@ public: return "test"; } + void start_accept() + { + session* new_session = new session(io_service_, context_); + acceptor_.async_accept(new_session->socket(), + boost::bind(&server::handle_accept, this, new_session, + asio::placeholders::error)); + } + void handle_accept(session* new_session, const asio::error_code& error) { if (!error) { new_session->start(); - new_session = new session(io_service_, context_); - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, - asio::placeholders::error)); } else { delete new_session; } + + start_accept(); } private: diff --git a/asio/src/examples/timeouts/server.cpp b/asio/src/examples/timeouts/server.cpp index dda824ac..d71f2249 100644 --- a/asio/src/examples/timeouts/server.cpp +++ b/asio/src/examples/timeouts/server.cpp @@ -365,6 +365,11 @@ public: subscriber_ptr bc(new udp_broadcaster(io_service_, broadcast_endpoint)); channel_.join(bc); + start_accept(); + } + + void start_accept() + { tcp_session_ptr new_session(new tcp_session(io_service_, channel_)); acceptor_.async_accept(new_session->socket(), @@ -377,12 +382,9 @@ public: if (!ec) { session->start(); - - tcp_session_ptr new_session(new tcp_session(io_service_, channel_)); - - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, _1)); } + + start_accept(); } private: diff --git a/asio/src/examples/tutorial/daytime3/server.cpp b/asio/src/examples/tutorial/daytime3/server.cpp index b64326e2..56927313 100644 --- a/asio/src/examples/tutorial/daytime3/server.cpp +++ b/asio/src/examples/tutorial/daytime3/server.cpp @@ -92,8 +92,9 @@ private: if (!error) { new_connection->start(); - start_accept(); } + + start_accept(); } tcp::acceptor acceptor_; diff --git a/asio/src/examples/tutorial/daytime7/server.cpp b/asio/src/examples/tutorial/daytime7/server.cpp index 44a30c68..11e32a0a 100644 --- a/asio/src/examples/tutorial/daytime7/server.cpp +++ b/asio/src/examples/tutorial/daytime7/server.cpp @@ -91,8 +91,9 @@ private: if (!error) { new_connection->start(); - start_accept(); } + + start_accept(); } tcp::acceptor acceptor_; diff --git a/asio/src/examples/windows/transmit_file.cpp b/asio/src/examples/windows/transmit_file.cpp index 148c7e29..4b637f9f 100644 --- a/asio/src/examples/windows/transmit_file.cpp +++ b/asio/src/examples/windows/transmit_file.cpp @@ -132,8 +132,9 @@ private: if (!error) { new_connection->start(); - start_accept(); } + + start_accept(); } tcp::acceptor acceptor_; diff --git a/asio/src/tests/performance/server.cpp b/asio/src/tests/performance/server.cpp index 97a851ff..ef6c45b6 100644 --- a/asio/src/tests/performance/server.cpp +++ b/asio/src/tests/performance/server.cpp @@ -155,6 +155,11 @@ public: acceptor_.bind(endpoint); acceptor_.listen(); + start_accept(); + } + + void start_accept() + { session* new_session = new session(io_service_, block_size_); acceptor_.async_accept(new_session->socket(), boost::bind(&server::handle_accept, this, new_session, @@ -166,15 +171,13 @@ public: if (!err) { new_session->start(); - new_session = new session(io_service_, block_size_); - acceptor_.async_accept(new_session->socket(), - boost::bind(&server::handle_accept, this, new_session, - asio::placeholders::error)); } else { delete new_session; } + + start_accept(); } private: