]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[5318] Call shutdown prior to closing the control socket.
authorMarcin Siodelski <marcin@isc.org>
Tue, 4 Jul 2017 07:47:02 +0000 (09:47 +0200)
committerMarcin Siodelski <marcin@isc.org>
Tue, 4 Jul 2017 07:47:02 +0000 (09:47 +0200)
src/lib/asiolink/unix_domain_socket.cc
src/lib/asiolink/unix_domain_socket.h
src/lib/config/command_mgr.cc
src/lib/config/config_messages.mes

index ae639df1387a2281496dfe4d01922ed8f37ab542..1551ec902609f73ee3d76fcfc28e972df18cea66 100644 (file)
@@ -145,6 +145,9 @@ public:
                         const boost::system::error_code& ec,
                         size_t length);
 
+    /// @brief Disables read and write operations on the socket.
+    void shutdown();
+
     /// @brief Closes the socket.
     void close();
 
@@ -244,9 +247,22 @@ UnixDomainSocketImpl::receiveHandler(const UnixDomainSocket::Handler& remote_han
     remote_handler(ec, length);
 }
 
+void
+UnixDomainSocketImpl::shutdown() {
+    boost::system::error_code ec;
+    static_cast<void>(socket_.shutdown(stream_protocol::socket::shutdown_both, ec));
+    if (ec) {
+        isc_throw(UnixDomainSocketError, ec.message());
+    }
+}
+
 void
 UnixDomainSocketImpl::close() {
-    static_cast<void>(socket_.close());
+    boost::system::error_code ec;
+    static_cast<void>(socket_.close(ec));
+    if (ec) {
+        isc_throw(UnixDomainSocketError, ec.message());
+    }
 }
 
 UnixDomainSocket::UnixDomainSocket(IOService& io_service)
@@ -312,6 +328,11 @@ UnixDomainSocket::asyncReceive(void* data, const size_t length,
     impl_->asyncReceive(data, length, handler);
 }
 
+void
+UnixDomainSocket::shutdown() {
+    impl_->shutdown();
+}
+
 void
 UnixDomainSocket::close() {
     impl_->close();
index ed8cfdd0ed0fa53590b797214dc0cd9754c0d9d8..6f0fe8c5179aa42d6d0e85a89f82e68d87b59127 100644 (file)
@@ -104,7 +104,14 @@ public:
     /// error is signalled.
     void asyncReceive(void* data, const size_t length, const Handler& handler);
 
+    /// @brief Disables read and write operations on the socket.
+    ///
+    /// @throw UnixDomainSocketError if an error occurs during shutdown.
+    void shutdown();
+
     /// @brief Closes the socket.
+    ///
+    /// @throw UnixDomainSocketError if an error occurs during closure.
     void close();
 
     /// @brief Returns reference to the underlying ASIO socket.
index 8795d7062ebbfdf9740d3161d6c540354a5ffa6f..6b4a7c044be96eeee0cae2a6ca9c2d65a7f497ef 100644 (file)
@@ -100,6 +100,12 @@ public:
         }
     }
 
+    /// @brief Gracefully terminates current connection.
+    ///
+    /// This method should be called prior to closing the socket to initiate
+    /// graceful shutdown.
+    void terminate();
+
     /// @brief Start asynchronous read over the unix domain socket.
     ///
     /// This method doesn't block. Once the transmission is received over the
@@ -213,6 +219,16 @@ private:
 
 };
 
+void
+Connection::terminate() {
+    try {
+        socket_->shutdown();
+
+    } catch (const std::exception& ex) {
+        LOG_ERROR(command_logger, COMMAND_SOCKET_CONNECTION_SHUTDOWN_FAIL)
+            .arg(ex.what());
+    }
+}
 
 void
 Connection::receiveHandler(const boost::system::error_code& ec,
@@ -320,6 +336,10 @@ Connection::sendHandler(const boost::system::error_code& ec,
             doSend();
             return;
         }
+
+        // Gracefully shutdown the connection and close the socket if
+        // we have sent the whole response.
+        terminate();
     }
 
     // All data sent or an error has occurred. Close the connection.
@@ -328,6 +348,9 @@ Connection::sendHandler(const boost::system::error_code& ec,
 
 void
 Connection::timeoutHandler() {
+    LOG_INFO(command_logger, COMMAND_SOCKET_CONNECTION_TIMEOUT)
+        .arg(socket_->getNative());
+
     ConstElementPtr rsp = createAnswer(CONTROL_RESULT_ERROR, "Connection over"
                                        " control channel timed out");
     response_ = rsp->str();
index 49aeb942a8d00772a4a478372df8e571dee24882..70c44f7f7703a0fba48ee08df5ad817e4cf5ddc0 100644 (file)
@@ -73,6 +73,15 @@ detailed error is provided as an argument.
 This is an informational message that a new incoming command connection was
 detected and a dedicated socket was opened for that connection.
 
+% COMMAND_SOCKET_CONNECTION_SHUTDOWN_FAIL Encountered error %1 while trying to gracefully shutdown socket
+This message indicates an error while trying to gracefully shutdown command
+connection. The type of the error is included in the message.
+
+% COMMAND_SOCKET_CONNECTION_TIMEOUT Timeout occurred for connection over socket %1
+This is an informational message that indicates that the timeout has
+occurred for one of the command channel connections. The response
+sent by the server indicates a timeout and is then closed.
+
 % COMMAND_SOCKET_READ Received %1 bytes over command socket %2
 This debug message indicates that specified number of bytes was received
 over command socket identified by specified file descriptor.