From 0ab956e03dd0a1df675a61a0579c4455ff4079a5 Mon Sep 17 00:00:00 2001 From: Ilay Rosenberg Date: Fri, 13 May 2022 12:16:55 +0300 Subject: [PATCH] Fix adding failed emitters on observer schedule (#872) * Moved `_add_emitter` call post emitter start so it isn't called if the emitter fails to start * Added test --- src/watchdog/observers/api.py | 2 +- tests/test_observer.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/watchdog/observers/api.py b/src/watchdog/observers/api.py index e5315873..47d7cee9 100644 --- a/src/watchdog/observers/api.py +++ b/src/watchdog/observers/api.py @@ -298,9 +298,9 @@ def schedule(self, event_handler, path, recursive=False): emitter = self._emitter_class(event_queue=self.event_queue, watch=watch, timeout=self.timeout) - self._add_emitter(emitter) if self.is_alive(): emitter.start() + self._add_emitter(emitter) self._watches.add(watch) return watch diff --git a/tests/test_observer.py b/tests/test_observer.py index 4ca5c77f..3e603d85 100644 --- a/tests/test_observer.py +++ b/tests/test_observer.py @@ -140,3 +140,22 @@ def mocked_start(): # Re-schduling the watch should work observer.schedule(None, '') assert len(observer.emitters) == 1 + + +def test_schedule_failure_should_not_prevent_future_schedules(monkeypatch, observer): + observer.start() + + # Make the emitter fail on start(), and subsequently the observer to fail on schedule() + def mocked_start(emitter): + raise OSError() + monkeypatch.setattr(EventEmitter, "start", mocked_start) + + with pytest.raises(OSError): + observer.schedule(None, '') + # The emitter should not be in the list + emitters = observer.emitters + assert len(emitters) == 0 + + # Re-schduling the watch should work + observer.schedule(None, '') + assert len(observer.emitters) == 1