Watchdog: Aufruf von inotify_init() auf jeder Uhr

Erstellt am 27. Sept. 2014  ·  3Kommentare  ·  Quelle: gorakhargosh/watchdog

Ich bekam den Fehler OSError: inotify instance limit reached mit nur etwa 50 offenen Beobachtern, was seltsam erschien. Also fing ich an zu graben und stellte fest, dass inotify_init() für so ziemlich jeden Beobachter aufgerufen wird: https://github.com/gorakhargosh/watchdog/blob/master/src/watchdog/observers/inotify_c.py#L163

Ich habe dies überprüft, indem ich eine Druckanweisung hinzugefügt und meine Nachricht für jede hinzugefügte Uhr ausgedruckt habe. Ich habe dann folgenden Workaround probiert:

--- a/watchdog/src/watchdog/observers/inotify_c.py
+++ b/watchdog/src/watchdog/observers/inotify_c.py
@@ -158,12 +158,19 @@ class Inotify(object):
         ``True`` if subdirectories should be monitored; ``False`` otherwise.
     """

+    _inotify_fd = None
+
     def __init__(self, path, recursive=False, event_mask=WATCHDOG_ALL_EVENTS):
         # The file descriptor associated with the inotify instance.
-        inotify_fd = inotify_init()
-        if inotify_fd == -1:
-            Inotify._raise_error()
-        self._inotify_fd = inotify_fd
+        if not Inotify._inotify_fd:
+            inotify_fd = inotify_init()
+
+            if inotify_fd == -1:
+                Inotify._raise_error()
+
+            Inotify._inotify_fd = inotify_fd
+
+        self._inotify_fd = Inotify._inotify_fd
         self._lock = threading.Lock()

         # Stores the watch descriptor for a given path.

Dies schien zu funktionieren, da Beobachter hinzugefügt werden, ohne auch die Anzahl der inotify-Instanzen über die erforderliche hinaus zu erhöhen. Dies unterbricht jedoch die eigentlichen Ereignisse sowie das Entfernen der Beobachter und gibt Fehler wie z

Exception in thread Thread-21:
Traceback (most recent call last):
  File "**/dist/python/lib/python2.7/threading.py", line 808, in __bootstrap_inner
    self.run()
  File "**/dist/bin/python/komodo/watchdog/observers/inotify_buffer.py", line 57, in run
    inotify_events = self._inotify.read_events()
  File "**/dist/bin/python/komodo/watchdog/observers/inotify_c.py", line 302, in read_events
    wd_path = self._path_for_wd[wd]
KeyError: 4

Ich zögere, zu diesem Zeitpunkt viel weiter zu graben, da ich mit dieser Codebasis nicht vertraut bin und die Auswirkungen nicht vollständig verstehe. Es scheint mir jedoch offensichtlich, dass das Hinzufügen einer Instanz für jede Uhr nicht das ist, was Sie tun sollten. Hoffentlich kann dies relativ einfach behoben werden, aber ich muss mich an Leute wenden, die diese Codebasis gründlich kennen.

inotify

Hilfreichster Kommentar

Beachten Sie, dass die "gesamte Inotify-API" aus etwa 3 Funktionen besteht, also nicht sicher, wie gültig dieser objektorientierte Ansatz ist. Ungeachtet dessen wird das Problem dadurch nicht behoben; watchdog fügt Instanzen für jeden Beobachter hinzu; Dies ist ein Fehler, egal welches Designprinzip Sie darauf anwenden.

Wenn es derzeit keinen aktiven Entwickler gibt, der mit diesem Code gründlich vertraut ist, würde ich gerne weiter damit spielen, um zu versuchen, eine richtige Lösung zu finden, aber ich mache mir hauptsächlich Sorgen, dass dies eine Menge Umschreibung erfordern würde, da dies offensichtlich nie der Fall war entwickelt, um mit einer einzigen inotify-Instanz zu arbeiten (obwohl es sollte). Mir scheint, dass dies ohne ein gründliches Verständnis der Funktionsweise von inotify implementiert wurde. Nun behaupte ich keineswegs, ein gründliches Verständnis von inotify zu haben (im Gegenteil), aber es scheint mir an dieser Stelle offensichtlich, dass Sie nicht für jeden Beobachter eine inotify-Instanz hinzufügen sollten.

Alle 3 Kommentare

Ich bin nicht der ursprüngliche Autor davon, aber ich glaube, dass die Klasse Inotify so gemacht wurde, um zu versuchen, einen objektorientierten Wrapper um die Inotify-API zu erstellen. Es kapselt die gesamte API, deshalb wird für jede Instanz ein inotify-Dateideskriptor erstellt. Anscheinend keine gute Idee, wenn Sie vorhaben, viele davon zu erstellen. Für mich ist das Inotify-Instanzlimit jedoch auf 128 festgelegt. Ich weiß nicht, warum Sie nur 50 erhalten haben. Vielleicht haben Sie andere Anwendungen, die Inotify-Instanzen erstellen.

Der Fehler, den Sie in read_events sehen, liegt daran, dass, wenn Sie einfach den Dateideskriptor freigeben, jede Instanz von Inotify aus demselben Dateideskriptor liest (siehe inotify_c.py#L284 ) und Ereignisse empfängt, die dies tun gehören nicht dazu.

Um nur einen Dateideskriptor zu verwenden, müssen Sie die Ereignislesung ebenfalls statisch machen und dann die Ereignisse an die Uhr verteilen, wo sie irgendwie hingehört.

Beachten Sie, dass die "gesamte Inotify-API" aus etwa 3 Funktionen besteht, also nicht sicher, wie gültig dieser objektorientierte Ansatz ist. Ungeachtet dessen wird das Problem dadurch nicht behoben; watchdog fügt Instanzen für jeden Beobachter hinzu; Dies ist ein Fehler, egal welches Designprinzip Sie darauf anwenden.

Wenn es derzeit keinen aktiven Entwickler gibt, der mit diesem Code gründlich vertraut ist, würde ich gerne weiter damit spielen, um zu versuchen, eine richtige Lösung zu finden, aber ich mache mir hauptsächlich Sorgen, dass dies eine Menge Umschreibung erfordern würde, da dies offensichtlich nie der Fall war entwickelt, um mit einer einzigen inotify-Instanz zu arbeiten (obwohl es sollte). Mir scheint, dass dies ohne ein gründliches Verständnis der Funktionsweise von inotify implementiert wurde. Nun behaupte ich keineswegs, ein gründliches Verständnis von inotify zu haben (im Gegenteil), aber es scheint mir an dieser Stelle offensichtlich, dass Sie nicht für jeden Beobachter eine inotify-Instanz hinzufügen sollten.

Abgesehen von dem unglücklich niedrigen Standardlimit gibt es meines Erachtens nichts, was besagt, dass Sie nur eine Inotify-Instanz erstellen müssen. Die APIs stimmen nicht überein. watchdog ist darauf ausgelegt, separate _Bäume_ zu überwachen, während einzelne Verzeichnisse oder Dateien auf Grund gelaufen sind. Versuchen Sie ruhig, eine Lösung vorzuschlagen. Wenn es Ihnen nichts ausmacht, Inotify-Überwachungen selbst zu verwalten, implementieren Sie alternativ ein EventEmitter , das nicht mehrere Inotify-Instanzen erstellt, aber Sie verlieren die Möglichkeit, unterschiedliche Ereignishandles für verschiedene Bäume zu haben.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen