Commit d912be1f authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[5318] Call shutdown prior to closing the control socket.

parent 82a6390b
......@@ -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();
......
......@@ -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.
......
......@@ -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();
......
......@@ -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.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment