From 043a0aeeebbbc50530ce195a4d43101327a31cd8 Mon Sep 17 00:00:00 2001 From: Fabio Erculiani Date: Thu, 12 Apr 2012 12:39:20 +0200 Subject: [PATCH] [entropy.misc] DirectoryMonitor: make possible to monitor multiple dirs --- lib/entropy/misc.py | 62 +++++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/lib/entropy/misc.py b/lib/entropy/misc.py index 36b2e6f33..8d5bad2ad 100644 --- a/lib/entropy/misc.py +++ b/lib/entropy/misc.py @@ -365,13 +365,15 @@ class DirectoryMonitor: DN_RENAME = fcntl.DN_RENAME # A file has got its attrs changed (perms, ownership) DN_ATTRIB = fcntl.DN_ATTRIB + # Keep signaling until the handler is explicitly removed + DN_MULTISHOT = fcntl.DN_MULTISHOT - def __init__(self, directory_path, callback, event_flags=None): + def __init__(self, directory_paths, callback, event_flags=None): """ DirectoryMonitor constructor. - @param directory_path: path of the directory to monitor - @type directory_path: string + @param directory_paths: list of paths of the directories to monitor + @type directory_paths: list @param callback: function called on events. The signature is: void function() @type callback: function @@ -380,7 +382,8 @@ class DirectoryMonitor: | DN_ATTRIB @type event_flags: int """ - self._directory_path = directory_path + self._directory_paths = directory_paths + self._signal_id = signal.SIGIO self._callback = callback if event_flags: self._flags = event_flags @@ -388,18 +391,25 @@ class DirectoryMonitor: self._flags = self.DN_ACCESS | self.DN_MODIFY | \ self.DN_CREATE | self.DN_DELETE | self.DN_RENAME | \ self.DN_ATTRIB - self._fd = os.open(self._directory_path, os.O_RDONLY) - fcntl.fcntl(self._fd, fcntl.F_NOTIFY, self._flags) + self._fds = [] + + for directory_path in self._directory_paths: + fd = os.open(directory_path, os.O_RDONLY) + fcntl.fcntl(fd, fcntl.F_NOTIFY, self._flags) + self._fds.append(fd) + def _forward(signum, frame): self._callback() - signal.signal(signal.SIGIO, _forward) + signal.signal(self._signal_id, _forward) def close(self): """ Terminate the listeners and release all the allocated resources. """ - signal.signal(signal.SIGIO, signal.SIG_DFL) - os.close(self._fd) + if self._fds: + signal.signal(self._signal_id, signal.SIG_DFL) + for fd in self._fds: + os.close(fd) class ParallelTask(threading.Thread): @@ -588,11 +598,16 @@ class FlockFile(object): Acquire the lock in shared mode. """ flags = fcntl.LOCK_SH - try: - fcntl.flock(self._f.fileno(), flags) - except IOError as err: - self.close() - raise + while True: + try: + fcntl.flock(self._f.fileno(), flags) + except IOError as err: + if err.errno == errno.EINTR: + # interrupted system call + continue + self.close() + raise + break def try_acquire_shared(self): """ @@ -605,6 +620,8 @@ class FlockFile(object): try: fcntl.flock(self._f.fileno(), flags) except IOError as err: + if err.errno == errno.EINTR: + return False if err.errno not in (errno.EACCES, errno.EAGAIN,): # ouch, wtf? self.close() @@ -617,11 +634,16 @@ class FlockFile(object): Acquire the lock in exclusive mode. """ flags = fcntl.LOCK_EX - try: - fcntl.flock(self._f.fileno(), flags) - except IOError as err: - self.close() - raise + while True: + try: + fcntl.flock(self._f.fileno(), flags) + except IOError as err: + if err.errno == errno.EINTR: + # interrupted system call + continue + self.close() + raise + break def try_acquire_exclusive(self): """ @@ -634,6 +656,8 @@ class FlockFile(object): try: fcntl.flock(self._f.fileno(), flags) except IOError as err: + if err.errno == errno.EINTR: + return False if err.errno not in (errno.EACCES, errno.EAGAIN,): # ouch, wtf? self.close()