約50人のウォッチャーしか開いていない状態でOSError: inotify instance limit reached
というエラーが発生していましたが、これは奇妙に思えました。 だから私は掘り始めて、inotify_init()がほとんど各ウォッチャーに呼び出されていることを発見しました: https ://github.com/gorakhargosh/watchdog/blob/master/src/watchdog/observers/inotify_c.py#L163
印刷ステートメントを追加し、追加された各時計のメッセージが出力されることを確認して、これを確認しました。 次に、次の回避策を試しました。
--- 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.
これは、必要な数を超えてinotifyインスタンスの数を増やすことなく、ウォッチャーが追加されるという点で機能しているように見えました。 ただし、これにより実際のイベントが中断されるだけでなく、ウォッチャーが削除され、次のようなエラーが発生します。
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
私はこのコードベースに精通していないため、その影響を完全には理解していないため、現時点ではさらに掘り下げることを躊躇しています。 時計ごとにインスタンスを追加することはあなたがすべきことではないことは私には明らかなようですが、これは比較的簡単に修正できることを願っていますが、このコードベースを完全に知っている人に任せる必要があります。
私はその元の作者ではありませんが、 Inotify
クラスは、inotifyapiの周りにオブジェクト指向ラッパーを作成するためにこのように行われたと思います。 API全体をカプセル化するため、インスタンスごとにinotifyファイル記述子が作成されます。 それらの多くを作成することを計画している場合は、明らかに良い考えではありません。 ただし、私にとっては、inotifyインスタンスの制限は128に設定されています。なぜ50しか得られなかったのかわかりません。おそらく、inotifyインスタンスを作成する他のアプリケーションがあります。
read_events
に表示されるエラーは、ファイル記述子を単純に共有すると、 Inotify
のすべてのインスタンスが同じファイル記述子( inotify_c.py#L284を参照)から読み取り、イベントを受信するためです。それに属していない。
1つのファイル記述子のみを使用するには、イベントの読み取りも静的にする必要があります。次に、イベントを何らかの方法で属するウォッチに配布します。
「InotifyAPI全体」は約3つの関数で構成されているため、このオブジェクト指向アプローチがどれほど有効かはわかりません。 とにかく、これは問題に対処しません。 ウォッチドッグは、ウォッチャーごとにインスタンスを追加しています。 これは、どの設計原則を適用してもバグです。
現在、このコードに精通しているアクティブな開発者がいない場合は、適切な修正を試みるためにさらに試してみてください。しかし、明らかに決してなかったので、これには大量の書き直しが必要になるのではないかと主に心配しています。単一のinotifyインスタンスで動作するように設計されています(必要な場合でも)。 これは、inotifyがどのように機能するかを完全に理解せずに実装されたようです。 今、私はinotifyを完全に理解しているとは言いませんが(逆に)、この時点で、ウォッチャーごとにinotifyインスタンスを追加するべきではないことは明らかです。
残念ながらデフォルトの下限に加えて、inotifyインスタンスを1つだけ作成する必要があるということは何もないと思います。 APIの不一致があります。 watchdogは、個別の_trees_を監視するように設計されており、座礁した単一のディレクトリまたはファイルをinotifyします。 解決策を提案してみてください。 または、inotifyウォッチを自分で管理してもかまわない場合は、複数のinotifyインスタンスを作成しないEventEmitter
を実装しますが、ツリーごとに異なるイベントハンドルを使用することはできなくなります。
最も参考になるコメント
「InotifyAPI全体」は約3つの関数で構成されているため、このオブジェクト指向アプローチがどれほど有効かはわかりません。 とにかく、これは問題に対処しません。 ウォッチドッグは、ウォッチャーごとにインスタンスを追加しています。 これは、どの設計原則を適用してもバグです。
現在、このコードに精通しているアクティブな開発者がいない場合は、適切な修正を試みるためにさらに試してみてください。しかし、明らかに決してなかったので、これには大量の書き直しが必要になるのではないかと主に心配しています。単一のinotifyインスタンスで動作するように設計されています(必要な場合でも)。 これは、inotifyがどのように機能するかを完全に理解せずに実装されたようです。 今、私はinotifyを完全に理解しているとは言いませんが(逆に)、この時点で、ウォッチャーごとにinotifyインスタンスを追加するべきではないことは明らかです。