From 7f1773e7e9ddbb7065b86e1d7654e5ee99c0db0d Mon Sep 17 00:00:00 2001 From: Guillaume Chazarain Date: Sun, 16 Jan 2011 00:23:36 +0100 Subject: [PATCH] Fix netlink message parsing to accept alignement padding. https://lkml.org/lkml/2010/12/13/176 https://lkml.org/lkml/2010/12/29/237 --- THANKS | 6 ++++++ iotop/data.py | 21 ++++++++++----------- iotop/genetlink.py | 18 ++++++++++++++---- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/THANKS b/THANKS index 4a136be..f318665 100644 --- a/THANKS +++ b/THANKS @@ -36,3 +36,9 @@ Philipp Thomas Jakub Wilk Contributed syscall numbers for getting and setting IO priority on armel and hppa architectures. + +Jeff Mahoney + Contributed a fixed implementation of the taskstats parsing code. + +Florian Mickler + Contributed a fixed implementation of the taskstats parsing code. diff --git a/iotop/data.py b/iotop/data.py index 1164344..41f23dd 100644 --- a/iotop/data.py +++ b/iotop/data.py @@ -136,6 +136,7 @@ TASKSTATS_CMD_GET = 1 TASKSTATS_CMD_ATTR_PID = 1 TASKSTATS_TYPE_AGGR_PID = 4 TASKSTATS_TYPE_PID = 1 +TASKSTATS_TYPE_STATS = 3 class TaskStatsNetlink(object): # Keep in sync with format_stats() and pinfo.did_some_io() @@ -154,24 +155,22 @@ class TaskStatsNetlink(object): def get_single_task_stats(self, thread): thread.task_stats_request.send(self.connection) try: - reply = self.connection.recv() + reply = GeNlMessage.recv(self.connection) except OSError, e: if e.errno == errno.ESRCH: # OSError: Netlink error: No such process (3) return raise - if len(reply.payload) < 292: + for attr_type, attr_value in reply.attrs.iteritems(): + if attr_type == TASKSTATS_TYPE_AGGR_PID: + reply = attr_value.nested() + break + else: + return + taskstats_data = reply[TASKSTATS_TYPE_STATS].data + if len(taskstats_data) < 272: # Short reply return - reply_length, reply_type = struct.unpack('HH', reply.payload[4:8]) - assert reply_length >= 288 - assert reply_type == TASKSTATS_TYPE_AGGR_PID - - pid_length, pid_type = struct.unpack('HH', reply.payload[8:12]) - assert pid_type == TASKSTATS_TYPE_PID - - taskstats_start = 4 + 4 + pid_length + 4 - taskstats_data = reply.payload[taskstats_start:] taskstats_version = struct.unpack('H', taskstats_data[:2])[0] assert taskstats_version >= 4 return Stats(taskstats_data) diff --git a/iotop/genetlink.py b/iotop/genetlink.py index ad977c4..0e4f954 100644 --- a/iotop/genetlink.py +++ b/iotop/genetlink.py @@ -45,6 +45,18 @@ class GeNlMessage(Message): Message.__init__(self, family, flags=flags, payload=[GenlHdr(self.cmd)]+attrs) + @staticmethod + def recv(conn): + msg = conn.recv() + packet = msg.payload + hdr = _genl_hdr_parse(packet[:4]) + + genlmsg = GeNlMessage(msg.type, hdr.cmd, [], msg.flags) + genlmsg.attrs = parse_attributes(packet[4:]) + genlmsg.version = hdr.version + + return genlmsg + class Controller: def __init__(self, conn): self.conn = conn @@ -53,10 +65,8 @@ class Controller: m = GeNlMessage(GENL_ID_CTRL, CTRL_CMD_GETFAMILY, flags=NLM_F_REQUEST, attrs=[a]) m.send(self.conn) - m = self.conn.recv() - gh = _genl_hdr_parse(m.payload[:4]) - attrs = parse_attributes(m.payload[4:]) - return attrs[CTRL_ATTR_FAMILY_ID].u16() + m = GeNlMessage.recv(self.conn) + return m.attrs[CTRL_ATTR_FAMILY_ID].u16() connection = Connection(NETLINK_GENERIC) controller = Controller(connection) -- 2.11.4.GIT