From 80ba43fbf514971a6a26118a7ffb26382a1d796d Mon Sep 17 00:00:00 2001 From: Ilay Rosenberg Date: Wed, 2 Feb 2022 17:22:50 +0200 Subject: [PATCH 1/2] Moved `_add_emitter` call post emitter start so it isn't called if the emitter fails to start --- src/watchdog/observers/api.py | 2 +- 1 file changed, 1 insertion(+), 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 From a42fca1681a3512dc8e96cb5f08515825a6badf4 Mon Sep 17 00:00:00 2001 From: Ilay Rosenberg Date: Wed, 2 Feb 2022 17:22:56 +0200 Subject: [PATCH 2/2] Added test --- tests/test_observer.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/test_observer.py b/tests/test_observer.py index cc4f8748..0cbc47d1 100644 --- a/tests/test_observer.py +++ b/tests/test_observer.py @@ -143,3 +143,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