Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r58628 - trunk/boost/asio/detail
From: chris_at_[hidden]
Date: 2010-01-02 04:48:03


Author: chris_kohlhoff
Date: 2010-01-02 04:48:01 EST (Sat, 02 Jan 2010)
New Revision: 58628
URL: http://svn.boost.org/trac/boost/changeset/58628

Log:
Don't block signals while performing system calls, but instead restart the
calls if they are interrupted.

Text files modified:
   trunk/boost/asio/detail/dev_poll_reactor.hpp | 3
   trunk/boost/asio/detail/epoll_reactor.hpp | 3
   trunk/boost/asio/detail/eventfd_select_interrupter.hpp | 39 +++++---
   trunk/boost/asio/detail/kqueue_reactor.hpp | 3
   trunk/boost/asio/detail/pipe_select_interrupter.hpp | 17 ++-
   trunk/boost/asio/detail/reactive_descriptor_service.hpp | 52 +++++++----
   trunk/boost/asio/detail/reactive_socket_service.hpp | 181 +++++++++++++++++++++++----------------
   trunk/boost/asio/detail/select_reactor.hpp | 3
   8 files changed, 177 insertions(+), 124 deletions(-)

Modified: trunk/boost/asio/detail/dev_poll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/dev_poll_reactor.hpp (original)
+++ trunk/boost/asio/detail/dev_poll_reactor.hpp 2010-01-02 04:48:01 EST (Sat, 02 Jan 2010)
@@ -402,9 +402,6 @@
     lock.lock();
     wait_in_progress_ = false;
 
- // Block signals while performing operations.
- boost::asio::detail::signal_blocker sb;
-
     // Dispatch the waiting events.
     for (int i = 0; i < num_events; ++i)
     {

Modified: trunk/boost/asio/detail/epoll_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/epoll_reactor.hpp (original)
+++ trunk/boost/asio/detail/epoll_reactor.hpp 2010-01-02 04:48:01 EST (Sat, 02 Jan 2010)
@@ -472,9 +472,6 @@
     lock.lock();
     wait_in_progress_ = false;
 
- // Block signals while performing operations.
- boost::asio::detail::signal_blocker sb;
-
     // Dispatch the waiting events.
     for (int i = 0; i < num_events; ++i)
     {

Modified: trunk/boost/asio/detail/eventfd_select_interrupter.hpp
==============================================================================
--- trunk/boost/asio/detail/eventfd_select_interrupter.hpp (original)
+++ trunk/boost/asio/detail/eventfd_select_interrupter.hpp 2010-01-02 04:48:01 EST (Sat, 02 Jan 2010)
@@ -24,14 +24,14 @@
 #include <boost/system/system_error.hpp>
 #include <boost/asio/detail/pop_options.hpp>
 
-#if defined(linux)
+#if defined(__linux__)
 # if !defined(BOOST_ASIO_DISABLE_EVENTFD)
 # include <linux/version.h>
 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
 # define BOOST_ASIO_HAS_EVENTFD
 # endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
 # endif // !defined(BOOST_ASIO_DISABLE_EVENTFD)
-#endif // defined(linux)
+#endif // defined(__linux__)
 
 #if defined(BOOST_ASIO_HAS_EVENTFD)
 
@@ -108,21 +108,32 @@
   {
     if (write_descriptor_ == read_descriptor_)
     {
- // Only perform one read. The kernel maintains an atomic counter.
- uint64_t counter(0);
- int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));
- bool was_interrupted = (bytes_read > 0);
- return was_interrupted;
+ for (;;)
+ {
+ // Only perform one read. The kernel maintains an atomic counter.
+ uint64_t counter(0);
+ errno = 0;
+ int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));
+ if (bytes_read < 0 && errno == EINTR)
+ continue;
+ bool was_interrupted = (bytes_read > 0);
+ return was_interrupted;
+ }
     }
     else
     {
- // Clear all data from the pipe.
- char data[1024];
- int bytes_read = ::read(read_descriptor_, data, sizeof(data));
- bool was_interrupted = (bytes_read > 0);
- while (bytes_read == sizeof(data))
- bytes_read = ::read(read_descriptor_, data, sizeof(data));
- return was_interrupted;
+ for (;;)
+ {
+ // Clear all data from the pipe.
+ char data[1024];
+ int bytes_read = ::read(read_descriptor_, data, sizeof(data));
+ if (bytes_read < 0 && errno == EINTR)
+ continue;
+ bool was_interrupted = (bytes_read > 0);
+ while (bytes_read == sizeof(data))
+ bytes_read = ::read(read_descriptor_, data, sizeof(data));
+ return was_interrupted;
+ }
     }
   }
 

Modified: trunk/boost/asio/detail/kqueue_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/kqueue_reactor.hpp (original)
+++ trunk/boost/asio/detail/kqueue_reactor.hpp 2010-01-02 04:48:01 EST (Sat, 02 Jan 2010)
@@ -442,9 +442,6 @@
     lock.lock();
     wait_in_progress_ = false;
 
- // Block signals while performing operations.
- boost::asio::detail::signal_blocker sb;
-
     // Dispatch the waiting events.
     for (int i = 0; i < num_events; ++i)
     {

Modified: trunk/boost/asio/detail/pipe_select_interrupter.hpp
==============================================================================
--- trunk/boost/asio/detail/pipe_select_interrupter.hpp (original)
+++ trunk/boost/asio/detail/pipe_select_interrupter.hpp 2010-01-02 04:48:01 EST (Sat, 02 Jan 2010)
@@ -79,12 +79,17 @@
   // Reset the select interrupt. Returns true if the call was interrupted.
   bool reset()
   {
- char data[1024];
- int bytes_read = ::read(read_descriptor_, data, sizeof(data));
- bool was_interrupted = (bytes_read > 0);
- while (bytes_read == sizeof(data))
- bytes_read = ::read(read_descriptor_, data, sizeof(data));
- return was_interrupted;
+ for (;;)
+ {
+ char data[1024];
+ int bytes_read = ::read(read_descriptor_, data, sizeof(data));
+ if (bytes_read < 0 && errno == EINTR)
+ continue;
+ bool was_interrupted = (bytes_read > 0);
+ while (bytes_read == sizeof(data))
+ bytes_read = ::read(read_descriptor_, data, sizeof(data));
+ return was_interrupted;
+ }
   }
 
   // Get the read descriptor to be passed to select.

Modified: trunk/boost/asio/detail/reactive_descriptor_service.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_descriptor_service.hpp (original)
+++ trunk/boost/asio/detail/reactive_descriptor_service.hpp 2010-01-02 04:48:01 EST (Sat, 02 Jan 2010)
@@ -348,16 +348,23 @@
             boost::asio::buffer_size(buffer));
       }
 
- // Write the data.
- int bytes = descriptor_ops::gather_write(descriptor_, bufs, i, ec);
+ for (;;)
+ {
+ // Write the data.
+ int bytes = descriptor_ops::gather_write(descriptor_, bufs, i, ec);
 
- // Check if we need to run the operation again.
- if (ec == boost::asio::error::would_block
- || ec == boost::asio::error::try_again)
- return false;
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
 
- bytes_transferred = (bytes < 0 ? 0 : bytes);
- return true;
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
+ return true;
+ }
     }
 
     void complete(const boost::system::error_code& ec,
@@ -600,18 +607,25 @@
             boost::asio::buffer_size(buffer));
       }
 
- // Read some data.
- int bytes = descriptor_ops::scatter_read(descriptor_, bufs, i, ec);
- if (bytes == 0)
- ec = boost::asio::error::eof;
-
- // Check if we need to run the operation again.
- if (ec == boost::asio::error::would_block
- || ec == boost::asio::error::try_again)
- return false;
+ for (;;)
+ {
+ // Read some data.
+ int bytes = descriptor_ops::scatter_read(descriptor_, bufs, i, ec);
+ if (bytes == 0)
+ ec = boost::asio::error::eof;
+
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
 
- bytes_transferred = (bytes < 0 ? 0 : bytes);
- return true;
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
+ return true;
+ }
     }
 
     void complete(const boost::system::error_code& ec,

Modified: trunk/boost/asio/detail/reactive_socket_service.hpp
==============================================================================
--- trunk/boost/asio/detail/reactive_socket_service.hpp (original)
+++ trunk/boost/asio/detail/reactive_socket_service.hpp 2010-01-02 04:48:01 EST (Sat, 02 Jan 2010)
@@ -644,16 +644,23 @@
             boost::asio::buffer_size(buffer));
       }
 
- // Send the data.
- int bytes = socket_ops::send(socket_, bufs, i, flags_, ec);
+ for (;;)
+ {
+ // Send the data.
+ int bytes = socket_ops::send(socket_, bufs, i, flags_, ec);
 
- // Check if we need to run the operation again.
- if (ec == boost::asio::error::would_block
- || ec == boost::asio::error::try_again)
- return false;
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
 
- bytes_transferred = (bytes < 0 ? 0 : bytes);
- return true;
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
+ return true;
+ }
     }
 
     void complete(const boost::system::error_code& ec,
@@ -881,17 +888,24 @@
             boost::asio::buffer_size(buffer));
       }
 
- // Send the data.
- int bytes = socket_ops::sendto(socket_, bufs, i, flags_,
- destination_.data(), destination_.size(), ec);
-
- // Check if we need to run the operation again.
- if (ec == boost::asio::error::would_block
- || ec == boost::asio::error::try_again)
- return false;
+ for (;;)
+ {
+ // Send the data.
+ int bytes = socket_ops::sendto(socket_, bufs, i, flags_,
+ destination_.data(), destination_.size(), ec);
+
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
 
- bytes_transferred = (bytes < 0 ? 0 : bytes);
- return true;
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
+ return true;
+ }
     }
 
     void complete(const boost::system::error_code& ec,
@@ -1086,18 +1100,25 @@
             boost::asio::buffer_size(buffer));
       }
 
- // Receive some data.
- int bytes = socket_ops::recv(socket_, bufs, i, flags_, ec);
- if (bytes == 0 && protocol_type_ == SOCK_STREAM)
- ec = boost::asio::error::eof;
-
- // Check if we need to run the operation again.
- if (ec == boost::asio::error::would_block
- || ec == boost::asio::error::try_again)
- return false;
+ for (;;)
+ {
+ // Receive some data.
+ int bytes = socket_ops::recv(socket_, bufs, i, flags_, ec);
+ if (bytes == 0 && protocol_type_ == SOCK_STREAM)
+ ec = boost::asio::error::eof;
+
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
 
- bytes_transferred = (bytes < 0 ? 0 : bytes);
- return true;
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
+ return true;
+ }
     }
 
     void complete(const boost::system::error_code& ec,
@@ -1331,21 +1352,28 @@
             boost::asio::buffer_size(buffer));
       }
 
- // Receive some data.
- std::size_t addr_len = sender_endpoint_.capacity();
- int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_,
- sender_endpoint_.data(), &addr_len, ec);
- if (bytes == 0 && protocol_type_ == SOCK_STREAM)
- ec = boost::asio::error::eof;
-
- // Check if we need to run the operation again.
- if (ec == boost::asio::error::would_block
- || ec == boost::asio::error::try_again)
- return false;
+ for (;;)
+ {
+ // Receive some data.
+ std::size_t addr_len = sender_endpoint_.capacity();
+ int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_,
+ sender_endpoint_.data(), &addr_len, ec);
+ if (bytes == 0 && protocol_type_ == SOCK_STREAM)
+ ec = boost::asio::error::eof;
+
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
 
- sender_endpoint_.resize(addr_len);
- bytes_transferred = (bytes < 0 ? 0 : bytes);
- return true;
+ sender_endpoint_.resize(addr_len);
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
+ return true;
+ }
     }
 
     void complete(const boost::system::error_code& ec,
@@ -1535,43 +1563,50 @@
       if (ec)
         return true;
 
- // Accept the waiting connection.
- socket_holder new_socket;
- std::size_t addr_len = 0;
- if (peer_endpoint_)
+ for (;;)
       {
- addr_len = peer_endpoint_->capacity();
- new_socket.reset(socket_ops::accept(socket_,
- peer_endpoint_->data(), &addr_len, ec));
- }
- else
- {
- new_socket.reset(socket_ops::accept(socket_, 0, 0, ec));
- }
+ // Accept the waiting connection.
+ socket_holder new_socket;
+ std::size_t addr_len = 0;
+ if (peer_endpoint_)
+ {
+ addr_len = peer_endpoint_->capacity();
+ new_socket.reset(socket_ops::accept(socket_,
+ peer_endpoint_->data(), &addr_len, ec));
+ }
+ else
+ {
+ new_socket.reset(socket_ops::accept(socket_, 0, 0, ec));
+ }
 
- // Check if we need to run the operation again.
- if (ec == boost::asio::error::would_block
- || ec == boost::asio::error::try_again)
- return false;
- if (ec == boost::asio::error::connection_aborted
- && !enable_connection_aborted_)
- return false;
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+ if (ec == boost::asio::error::connection_aborted
+ && !enable_connection_aborted_)
+ return false;
 #if defined(EPROTO)
- if (ec.value() == EPROTO && !enable_connection_aborted_)
- return false;
+ if (ec.value() == EPROTO && !enable_connection_aborted_)
+ return false;
 #endif // defined(EPROTO)
 
- // Transfer ownership of the new socket to the peer object.
- if (!ec)
- {
- if (peer_endpoint_)
- peer_endpoint_->resize(addr_len);
- peer_.assign(protocol_, new_socket.get(), ec);
+ // Transfer ownership of the new socket to the peer object.
         if (!ec)
- new_socket.release();
- }
+ {
+ if (peer_endpoint_)
+ peer_endpoint_->resize(addr_len);
+ peer_.assign(protocol_, new_socket.get(), ec);
+ if (!ec)
+ new_socket.release();
+ }
 
- return true;
+ return true;
+ }
     }
 
     void complete(const boost::system::error_code& ec, std::size_t)

Modified: trunk/boost/asio/detail/select_reactor.hpp
==============================================================================
--- trunk/boost/asio/detail/select_reactor.hpp (original)
+++ trunk/boost/asio/detail/select_reactor.hpp 2010-01-02 04:48:01 EST (Sat, 02 Jan 2010)
@@ -369,9 +369,6 @@
     lock.lock();
     select_in_progress_ = false;
 
- // Block signals while dispatching operations.
- boost::asio::detail::signal_blocker sb;
-
     // Reset the interrupter.
     if (retval > 0 && read_fds.is_set(interrupter_.read_descriptor()))
       interrupter_.reset();


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk