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.master
parent
b7070876e5
commit
eefcc554c0
|
@ -119,9 +119,9 @@ class InotifyError(OSError):
|
||||||
class Inotify(object):
|
class Inotify(object):
|
||||||
'''Wrapper class for Linux inotify capabilities'''
|
'''Wrapper class for Linux inotify capabilities'''
|
||||||
|
|
||||||
BUFSIZE = 4096
|
|
||||||
STRUCT_FMT = '@iIII'
|
STRUCT_FMT = '@iIII'
|
||||||
STRUCT_SIZE = struct.calcsize(STRUCT_FMT)
|
STRUCT_SIZE = struct.calcsize(STRUCT_FMT)
|
||||||
|
BUFSIZE = STRUCT_SIZE + 256
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
fd = _libc.inotify_init()
|
fd = _libc.inotify_init()
|
||||||
|
@ -173,21 +173,19 @@ class Inotify(object):
|
||||||
|
|
||||||
buf = memoryview(os.read(self.__fd, self.BUFSIZE))
|
buf = memoryview(os.read(self.__fd, self.BUFSIZE))
|
||||||
nread = len(buf)
|
nread = len(buf)
|
||||||
i = begin = 0
|
pos = 0
|
||||||
end = self.STRUCT_SIZE
|
while pos < nread:
|
||||||
while i < nread:
|
packed = buf[pos:pos + self.STRUCT_SIZE]
|
||||||
wd, mask, cookie, sz = self._unpack(buf[begin:end])
|
pos += self.STRUCT_SIZE
|
||||||
begin = end
|
wd, mask, cookie, sz = self._unpack(packed)
|
||||||
end += sz
|
if sz:
|
||||||
x = begin
|
name = buf[pos:pos + sz].tobytes()
|
||||||
while buf[x:x + 1] != b'\x00':
|
name = name[:name.index(b'\x00')]
|
||||||
x += 1
|
pos += sz
|
||||||
name = buf[begin:x].tobytes()
|
else:
|
||||||
|
name = None
|
||||||
pathname = self.__watches[wd]
|
pathname = self.__watches[wd]
|
||||||
i += end
|
|
||||||
yield Event(wd, mask, cookie, name, pathname)
|
yield Event(wd, mask, cookie, name, pathname)
|
||||||
begin = end
|
|
||||||
end += self.STRUCT_SIZE
|
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
'''Close all watch descriptors and the inotify descriptor'''
|
'''Close all watch descriptors and the inotify descriptor'''
|
||||||
|
|
Loading…
Reference in New Issue