Browse Source

[2903] make sure UDPServer don't die due to a failure of close().

also don't stop receiving due to errors from async_receive_from().
some other minor cleanups are made too.
JINMEI Tatuya 12 years ago
parent
commit
abd65c5b6e
2 changed files with 25 additions and 8 deletions
  1. 8 0
      src/lib/asiodns/asiodns_messages.mes
  2. 17 8
      src/lib/asiodns/udp_server.cc

+ 8 - 0
src/lib/asiodns/asiodns_messages.mes

@@ -75,6 +75,14 @@ If you see a single occurrence of this message, it probably does not
 indicate any significant problem, but if it is logged often, it is probably
 indicate any significant problem, but if it is logged often, it is probably
 a good idea to inspect your network traffic.
 a good idea to inspect your network traffic.
 
 
+% ASIODNS_UDP_RECEIVE_FAIL failed to accept UDP DNS packet: %1
+Receiving a UDP packet from a DNS client failed due to an error that
+could happen but should be very rare.  The server still keeps
+receiving UDP packets on this socket.  The reason for the error is
+included in the log message.  This log message is basically not
+expected to appear at all in practice; if it does, there may be some
+system level failure and other system logs may have to be checked.
+
 % ASIODNS_UDP_SYNC_SEND_FAIL Error sending UDP packet to %1: %2
 % ASIODNS_UDP_SYNC_SEND_FAIL Error sending UDP packet to %1: %2
 The low-level ASIO library reported an error when trying to send a UDP
 The low-level ASIO library reported an error when trying to send a UDP
 packet in synchronous UDP mode. See ASIODNS_UDP_ASYNC_SEND_FAIL for
 packet in synchronous UDP mode. See ASIODNS_UDP_ASYNC_SEND_FAIL for

+ 17 - 8
src/lib/asiodns/udp_server.cc

@@ -212,14 +212,19 @@ UDPServer::operator()(asio::error_code ec, size_t length) {
                     buffer(data_->data_.get(), MAX_LENGTH), *data_->sender_,
                     buffer(data_->data_.get(), MAX_LENGTH), *data_->sender_,
                     *this);
                     *this);
 
 
-                // Abort on fatal errors
+                // See TCPServer::operator() for details on error handling.
-                // TODO: add log
                 if (ec) {
                 if (ec) {
                     using namespace asio::error;
                     using namespace asio::error;
-                    if (ec.value() != would_block && ec.value() != try_again &&
+                    const error_code::value_type err_val = ec.value();
-                        ec.value() != interrupted) {
+                    if (err_val == operation_aborted ||
+                        err_val == bad_descriptor) {
                         return;
                         return;
                     }
                     }
+                    if (err_val != would_block && err_val != try_again &&
+                        err_val != interrupted) {
+                        LOG_ERROR(logger, ASIODNS_UDP_RECEIVE_FAIL).
+                            arg(ec.message());
+                    }
                 }
                 }
 
 
             } while (ec || length == 0);
             } while (ec || length == 0);
@@ -270,7 +275,7 @@ UDPServer::operator()(asio::error_code ec, size_t length) {
         // If we don't have a DNS Lookup provider, there's no point in
         // If we don't have a DNS Lookup provider, there's no point in
         // continuing; we exit the coroutine permanently.
         // continuing; we exit the coroutine permanently.
         if (data_->lookup_callback_ == NULL) {
         if (data_->lookup_callback_ == NULL) {
-            CORO_YIELD return;
+            return;
         }
         }
 
 
         // Instantiate objects that will be needed by the
         // Instantiate objects that will be needed by the
@@ -287,7 +292,7 @@ UDPServer::operator()(asio::error_code ec, size_t length) {
         // The 'done_' flag indicates whether we have an answer
         // The 'done_' flag indicates whether we have an answer
         // to send back.  If not, exit the coroutine permanently.
         // to send back.  If not, exit the coroutine permanently.
         if (!data_->done_) {
         if (!data_->done_) {
-            CORO_YIELD return;
+            return;
         }
         }
 
 
         // Call the DNS answer provider to render the answer into
         // Call the DNS answer provider to render the answer into
@@ -322,6 +327,10 @@ UDPServer::asyncLookup() {
 /// Stop the UDPServer
 /// Stop the UDPServer
 void
 void
 UDPServer::stop() {
 UDPServer::stop() {
+    // passing error_code to avoid getting exception; we simply ignore any
+    // error on close().
+    asio::error_code ec;
+
     /// Using close instead of cancel, because cancel
     /// Using close instead of cancel, because cancel
     /// will only cancel the asynchronized event already submitted
     /// will only cancel the asynchronized event already submitted
     /// to io service, the events post to io service after
     /// to io service, the events post to io service after
@@ -330,7 +339,7 @@ UDPServer::stop() {
     /// for it won't be scheduled by io service not matter it is
     /// for it won't be scheduled by io service not matter it is
     /// submit to io service before or after close call. And we will
     /// submit to io service before or after close call. And we will
     //  get bad_descriptor error.
     //  get bad_descriptor error.
-    data_->socket_->close();
+    data_->socket_->close(ec);
 }
 }
 
 
 /// Post this coroutine on the ASIO service queue so that it will
 /// Post this coroutine on the ASIO service queue so that it will
@@ -339,7 +348,7 @@ UDPServer::stop() {
 void
 void
 UDPServer::resume(const bool done) {
 UDPServer::resume(const bool done) {
     data_->done_ = done;
     data_->done_ = done;
-    data_->io_.post(*this);
+    data_->io_.post(*this);  // this can throw, but can be considered fatal.
 }
 }
 
 
 } // namespace asiodns
 } // namespace asiodns