2 // process_per_connection.cpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 #include <boost/asio/io_service.hpp>
12 #include <boost/asio/ip/tcp.hpp>
13 #include <boost/asio/signal_set.hpp>
14 #include <boost/asio/write.hpp>
15 #include <boost/array.hpp>
16 #include <boost/bind.hpp>
19 #include <sys/types.h>
23 using boost::asio::ip::tcp;
28 server(boost::asio::io_service& io_service, unsigned short port)
29 : io_service_(io_service),
30 signal_(io_service, SIGCHLD),
31 acceptor_(io_service, tcp::endpoint(tcp::v4(), port)),
39 void start_signal_wait()
41 signal_.async_wait(boost::bind(&server::handle_signal_wait, this));
44 void handle_signal_wait()
46 // Only the parent process should check for this signal. We can determine
47 // whether we are in the parent by checking if the acceptor is still open.
48 if (acceptor_.is_open())
50 // Reap completed child processes so that we don't end up with zombies.
52 while (waitpid(-1, &status, WNOHANG) > 0) {}
60 acceptor_.async_accept(socket_,
61 boost::bind(&server::handle_accept, this, _1));
64 void handle_accept(const boost::system::error_code& ec)
68 // Inform the io_service that we are about to fork. The io_service cleans
69 // up any internal resources, such as threads, that may interfere with
71 io_service_.notify_fork(boost::asio::io_service::fork_prepare);
75 // Inform the io_service that the fork is finished and that this is the
76 // child process. The io_service uses this opportunity to create any
77 // internal file descriptors that must be private to the new process.
78 io_service_.notify_fork(boost::asio::io_service::fork_child);
80 // The child won't be accepting new connections, so we can close the
81 // acceptor. It remains open in the parent.
84 // The child process is not interested in processing the SIGCHLD signal.
91 // Inform the io_service that the fork is finished (or failed) and that
92 // this is the parent process. The io_service uses this opportunity to
93 // recreate any internal resources that were cleaned up during
94 // preparation for the fork.
95 io_service_.notify_fork(boost::asio::io_service::fork_parent);
103 std::cerr << "Accept error: " << ec.message() << std::endl;
110 socket_.async_read_some(boost::asio::buffer(data_),
111 boost::bind(&server::handle_read, this, _1, _2));
114 void handle_read(const boost::system::error_code& ec, std::size_t length)
120 void start_write(std::size_t length)
122 boost::asio::async_write(socket_, boost::asio::buffer(data_, length),
123 boost::bind(&server::handle_write, this, _1));
126 void handle_write(const boost::system::error_code& ec)
132 boost::asio::io_service& io_service_;
133 boost::asio::signal_set signal_;
134 tcp::acceptor acceptor_;
136 boost::array<char, 1024> data_;
139 int main(int argc, char* argv[])
145 std::cerr << "Usage: process_per_connection <port>\n";
149 boost::asio::io_service io_service;
151 using namespace std; // For atoi.
152 server s(io_service, atoi(argv[1]));
156 catch (std::exception& e)
158 std::cerr << "Exception: " << e.what() << std::endl;