inotify: Correctly handle multi-struct reads
When reading from the *inotify* file descriptor, multiple structs can be returned. Because the read loop was incorrectly calculating offsets, messages would frequently get lost in this way. This commit simplifies the logic of the read loop, using only a single position indicator and correctly calculating all offsets from that on each iteration. The result is that no more messages are incorrectly skipped.
This commit is contained in:
@@ -119,9 +119,9 @@ class InotifyError(OSError):
|
||||
class Inotify(object):
|
||||
'''Wrapper class for Linux inotify capabilities'''
|
||||
|
||||
BUFSIZE = 4096
|
||||
STRUCT_FMT = '@iIII'
|
||||
STRUCT_SIZE = struct.calcsize(STRUCT_FMT)
|
||||
BUFSIZE = STRUCT_SIZE + 256
|
||||
|
||||
def __init__(self):
|
||||
fd = _libc.inotify_init()
|
||||
@@ -173,21 +173,19 @@ class Inotify(object):
|
||||
|
||||
buf = memoryview(os.read(self.__fd, self.BUFSIZE))
|
||||
nread = len(buf)
|
||||
i = begin = 0
|
||||
end = self.STRUCT_SIZE
|
||||
while i < nread:
|
||||
wd, mask, cookie, sz = self._unpack(buf[begin:end])
|
||||
begin = end
|
||||
end += sz
|
||||
x = begin
|
||||
while buf[x:x + 1] != b'\x00':
|
||||
x += 1
|
||||
name = buf[begin:x].tobytes()
|
||||
pos = 0
|
||||
while pos < nread:
|
||||
packed = buf[pos:pos + self.STRUCT_SIZE]
|
||||
pos += self.STRUCT_SIZE
|
||||
wd, mask, cookie, sz = self._unpack(packed)
|
||||
if sz:
|
||||
name = buf[pos:pos + sz].tobytes()
|
||||
name = name[:name.index(b'\x00')]
|
||||
pos += sz
|
||||
else:
|
||||
name = None
|
||||
pathname = self.__watches[wd]
|
||||
i += end
|
||||
yield Event(wd, mask, cookie, name, pathname)
|
||||
begin = end
|
||||
end += self.STRUCT_SIZE
|
||||
|
||||
def close(self):
|
||||
'''Close all watch descriptors and the inotify descriptor'''
|
||||
|
||||
Reference in New Issue
Block a user