mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-01 06:25:34 +00:00
[2617] reorder log message; some more comments and doc
This commit is contained in:
@@ -71,6 +71,15 @@ SPECFILE_LOCATION = SPECFILE_PATH + "/msgq.spec"
|
|||||||
class MsgQReceiveError(Exception): pass
|
class MsgQReceiveError(Exception): pass
|
||||||
|
|
||||||
class MsgQCloseOnReceive(Exception):
|
class MsgQCloseOnReceive(Exception):
|
||||||
|
'''Exception raised when reading data from a socket results in "shutdown.
|
||||||
|
|
||||||
|
This can be either getting 0-length data or via ECONNRESET socket.error
|
||||||
|
exception. This class holds whether it happens in the middle of reading
|
||||||
|
(i.e. after reading some) via partial_read parameter, which is set to True
|
||||||
|
if and only if so. This will be used by an upper layer cathing the
|
||||||
|
exception to distinguish severity of the event.
|
||||||
|
|
||||||
|
"'''
|
||||||
def __init__(self, reason, partial_read):
|
def __init__(self, reason, partial_read):
|
||||||
self.partial_read = partial_read
|
self.partial_read = partial_read
|
||||||
self.__reason = reason
|
self.__reason = reason
|
||||||
@@ -328,8 +337,12 @@ class MsgQ:
|
|||||||
|
|
||||||
def kill_socket(self, fd, sock):
|
def kill_socket(self, fd, sock):
|
||||||
"""Fully close down the socket."""
|
"""Fully close down the socket."""
|
||||||
|
# Unregister events on the socket. Note that we don't have to do
|
||||||
|
# this for kqueue because the registered events are automatically
|
||||||
|
# deleted when the corresponding socket is closed.
|
||||||
if self.poller:
|
if self.poller:
|
||||||
self.poller.unregister(sock)
|
self.poller.unregister(sock)
|
||||||
|
|
||||||
self.subs.unsubscribe_all(sock)
|
self.subs.unsubscribe_all(sock)
|
||||||
lname = [ k for k, v in self.lnames.items() if v == sock ][0]
|
lname = [ k for k, v in self.lnames.items() if v == sock ][0]
|
||||||
del self.lnames[lname]
|
del self.lnames[lname]
|
||||||
@@ -341,11 +354,20 @@ class MsgQ:
|
|||||||
|
|
||||||
def __getbytes(self, fd, sock, length, continued):
|
def __getbytes(self, fd, sock, length, continued):
|
||||||
"""Get exactly the requested bytes, or raise an exception if
|
"""Get exactly the requested bytes, or raise an exception if
|
||||||
EOF."""
|
EOF.
|
||||||
|
|
||||||
|
continued is set to True if this method is called to complete
|
||||||
|
already read data.
|
||||||
|
"""
|
||||||
received = b''
|
received = b''
|
||||||
while len(received) < length:
|
while len(received) < length:
|
||||||
try:
|
try:
|
||||||
data = sock.recv(length - len(received))
|
data = sock.recv(length - len(received))
|
||||||
|
|
||||||
|
# If the remote client has closed the socket there seems to be
|
||||||
|
# two possible cases: getting ECONNRESET or receiving empty data.
|
||||||
|
# These cases are possible in normal operation, so we report them
|
||||||
|
# using MsgQCloseOnReceive.
|
||||||
except socket.error as err:
|
except socket.error as err:
|
||||||
if err.errno == errno.ECONNRESET:
|
if err.errno == errno.ECONNRESET:
|
||||||
raise MsgQCloseOnReceive(str(err), continued)
|
raise MsgQCloseOnReceive(str(err), continued)
|
||||||
@@ -382,6 +404,10 @@ class MsgQ:
|
|||||||
try:
|
try:
|
||||||
routing, data = self.read_packet(fd, sock)
|
routing, data = self.read_packet(fd, sock)
|
||||||
except (MsgQReceiveError, MsgQCloseOnReceive) as err:
|
except (MsgQReceiveError, MsgQCloseOnReceive) as err:
|
||||||
|
# If it's MsgQCloseOnReceive and that happens without reading
|
||||||
|
# any data, it basically means the remote clinet has closed the
|
||||||
|
# socket, so we log it as debug information. Otherwise, it's
|
||||||
|
# a somewhat unexpected event, so we consider it an "error".
|
||||||
if isinstance(err, MsgQCloseOnReceive) and not err.partial_read:
|
if isinstance(err, MsgQCloseOnReceive) and not err.partial_read:
|
||||||
logger.debug(TRACE_BASIC, MSGQ_CLOSE_ON_RECV, fd)
|
logger.debug(TRACE_BASIC, MSGQ_CLOSE_ON_RECV, fd)
|
||||||
else:
|
else:
|
||||||
|
@@ -23,6 +23,31 @@
|
|||||||
This is a debug message. The message queue has little bit of special handling
|
This is a debug message. The message queue has little bit of special handling
|
||||||
for the configuration manager. This special handling is happening now.
|
for the configuration manager. This special handling is happening now.
|
||||||
|
|
||||||
|
% MSGQ_CLOSE_ON_RECV Reading from socket canceled as it's closed: FD=%1
|
||||||
|
A debug message. The msgq daemon was notified of a read event on a
|
||||||
|
socket, but its initial read operation failed because the remote
|
||||||
|
client has closed its socket. This is possible in a normal operation
|
||||||
|
when a module shuts down.
|
||||||
|
|
||||||
|
% MSGQ_CLOSE_ON_SEND Sending to socket failed as already closed (okay to ignore on shutdown): FD=%1
|
||||||
|
The msgq daemon tries to send some data to a client module, but it
|
||||||
|
failed because the socket has been closed. This normally means the
|
||||||
|
client terminates (for some reason - either gracefully or as a crash)
|
||||||
|
while other modules try to send a message to the terminated module.
|
||||||
|
Since msgq doesn't keep track of the status of client modules, this
|
||||||
|
can happen and is not really an error for msgq; however, it can still
|
||||||
|
be an unexpected event for the BIND 10 system as a whole in that this
|
||||||
|
particular message is lost, so it's logged as a warning. If this
|
||||||
|
message is logged for a running BIND 10 system, it's suggested to
|
||||||
|
check other log messages; there may be an error from other modules
|
||||||
|
reporting a missing response message. One common, less critical case
|
||||||
|
where this message is logged is during shutdown. The ordering of
|
||||||
|
process shutdown is basically arbitrary at this moment, so it's
|
||||||
|
possible that some module tries to send a "quitting" message to some
|
||||||
|
other module but the latter has already shut down. Such cases are
|
||||||
|
generally non critical, but you may want to check other possible error
|
||||||
|
messages.
|
||||||
|
|
||||||
% MSGQ_COMMAND Running command %1 with arguments %2
|
% MSGQ_COMMAND Running command %1 with arguments %2
|
||||||
Debug message. The message queue received a command and it is running it.
|
Debug message. The message queue received a command and it is running it.
|
||||||
|
|
||||||
@@ -83,25 +108,6 @@ Debug message. This message includes the whole routing header of a packet.
|
|||||||
There was a low-level error when sending data to a socket. The error is logged
|
There was a low-level error when sending data to a socket. The error is logged
|
||||||
and the corresponding socket is dropped.
|
and the corresponding socket is dropped.
|
||||||
|
|
||||||
% MSGQ_CLOSE_ON_SEND Sending to socket failed as already closed (okay to ignore on shutdown): FD=%1
|
|
||||||
The msgq daemon tries to send some data to a client module, but it
|
|
||||||
failed because the socket has been closed. This normally means the
|
|
||||||
client terminates (for some reason - either gracefully or as a crash)
|
|
||||||
while other modules try to send a message to the terminated module.
|
|
||||||
Since msgq doesn't keep track of the status of client modules, this
|
|
||||||
can happen and is not really an error for msgq; however, it can still
|
|
||||||
be an unexpected event for the BIND 10 system as a whole in that this
|
|
||||||
particular message is lost, so it's logged as a warning. If this
|
|
||||||
message is logged for a running BIND 10 system, it's suggested to
|
|
||||||
check other log messages; there may be an error from other modules
|
|
||||||
reporting a missing response message. One common, less critical case
|
|
||||||
where this message is logged is during shutdown. The ordering of
|
|
||||||
process shutdown is basically arbitrary at this moment, so it's
|
|
||||||
possible that some module tries to send a "quitting" message to some
|
|
||||||
other module but the latter has already shut down. Such cases are
|
|
||||||
generally non critical, but you may want to check other possible error
|
|
||||||
messages.
|
|
||||||
|
|
||||||
% MSGQ_SHUTDOWN Stopping Msgq
|
% MSGQ_SHUTDOWN Stopping Msgq
|
||||||
Debug message. The message queue is shutting down.
|
Debug message. The message queue is shutting down.
|
||||||
|
|
||||||
@@ -127,9 +133,3 @@ data structure.
|
|||||||
% MSGQ_SUBS_NEW_TARGET Creating new target for subscription to group '%1' for instance '%2'
|
% MSGQ_SUBS_NEW_TARGET Creating new target for subscription to group '%1' for instance '%2'
|
||||||
Debug message. Creating a new subscription. Also creating a new data structure
|
Debug message. Creating a new subscription. Also creating a new data structure
|
||||||
to hold it.
|
to hold it.
|
||||||
|
|
||||||
% MSGQ_CLOSE_ON_RECV Reading from socket canceled as it's closed: FD=%1
|
|
||||||
A debug message. The msgq daemon was notified of a read event on a
|
|
||||||
socket, but its initial read operation failed because the remote
|
|
||||||
client has closed its socket. This is possible in a normal operation
|
|
||||||
when a module shuts down.
|
|
||||||
|
@@ -659,6 +659,7 @@ class SocketTests(unittest.TestCase):
|
|||||||
for eno in [errno.EPIPE, errno.ECONNRESET, errno.ENOBUFS]:
|
for eno in [errno.EPIPE, errno.ECONNRESET, errno.ENOBUFS]:
|
||||||
self.__sock_error.errno = eno
|
self.__sock_error.errno = eno
|
||||||
self.__sock.ex_on_send = self.__sock_error
|
self.__sock.ex_on_send = self.__sock_error
|
||||||
|
self.__killed_socket = None # clear any previuos value
|
||||||
self.assertEqual(None, self.__msgq._send_data(self.__sock,
|
self.assertEqual(None, self.__msgq._send_data(self.__sock,
|
||||||
self.__data))
|
self.__data))
|
||||||
self.assertEqual((42, self.__sock), self.__killed_socket)
|
self.assertEqual((42, self.__sock), self.__killed_socket)
|
||||||
@@ -703,9 +704,13 @@ class SocketTests(unittest.TestCase):
|
|||||||
expected_errors = 0
|
expected_errors = 0
|
||||||
expected_debugs = 0
|
expected_debugs = 0
|
||||||
|
|
||||||
|
# if socket.recv() fails due to socket.error, it will be logged
|
||||||
|
# as error or debug depending on the errno. In either case the socket
|
||||||
|
# will be killed.
|
||||||
for eno in [errno.ENOBUFS, errno.ECONNRESET]:
|
for eno in [errno.ENOBUFS, errno.ECONNRESET]:
|
||||||
self.__sock_error.errno = eno
|
self.__sock_error.errno = eno
|
||||||
self.__sock.recv_result = self.__sock_error
|
self.__sock.recv_result = self.__sock_error
|
||||||
|
self.__killed_socket = None # clear any previuos value
|
||||||
self.__msgq.process_packet(42, self.__sock)
|
self.__msgq.process_packet(42, self.__sock)
|
||||||
self.assertEqual((42, self.__sock), self.__killed_socket)
|
self.assertEqual((42, self.__sock), self.__killed_socket)
|
||||||
if eno == errno.ENOBUFS:
|
if eno == errno.ENOBUFS:
|
||||||
@@ -715,8 +720,13 @@ class SocketTests(unittest.TestCase):
|
|||||||
self.assertEqual(expected_errors, self.__logger.error_called)
|
self.assertEqual(expected_errors, self.__logger.error_called)
|
||||||
self.assertEqual(expected_debugs, self.__logger.debug_called)
|
self.assertEqual(expected_debugs, self.__logger.debug_called)
|
||||||
|
|
||||||
|
# if socket.recv() returns empty data, the result depends on whether
|
||||||
|
# there's any preceding data; in the second case below, at least
|
||||||
|
# 6 bytes of data will be expected, and the second call to our faked
|
||||||
|
# recv() returns empty data. In that case it will logged as error.
|
||||||
for recv_data in [b'', b'short']:
|
for recv_data in [b'', b'short']:
|
||||||
self.__sock.recv_result = recv_data
|
self.__sock.recv_result = recv_data
|
||||||
|
self.__killed_socket = None
|
||||||
self.__msgq.process_packet(42, self.__sock)
|
self.__msgq.process_packet(42, self.__sock)
|
||||||
self.assertEqual((42, self.__sock), self.__killed_socket)
|
self.assertEqual((42, self.__sock), self.__killed_socket)
|
||||||
if len(recv_data) == 0:
|
if len(recv_data) == 0:
|
||||||
|
Reference in New Issue
Block a user