diff --git a/google/cloud/firestore_v1/watch.py b/google/cloud/firestore_v1/watch.py index 62b53ef4a..79933aeca 100644 --- a/google/cloud/firestore_v1/watch.py +++ b/google/cloud/firestore_v1/watch.py @@ -440,6 +440,9 @@ def on_snapshot(self, proto): proto(`google.cloud.firestore_v1.types.ListenResponse`): Callback method that receives a object to """ + if self._closing.locked(): + # don't process on_snapshot responses while spinning down, to prevent deadlock + return if proto is None: self.close() return diff --git a/tests/unit/v1/test_watch.py b/tests/unit/v1/test_watch.py index 094248e93..6d8c12abc 100644 --- a/tests/unit/v1/test_watch.py +++ b/tests/unit/v1/test_watch.py @@ -400,6 +400,15 @@ def test_watch_on_snapshot_target_w_none(): assert inst._rpc is None +def test_watch_on_snapshot_while_closing(): + inst = _make_watch() + inst.close = mock.Mock() + with inst._closing: + inst.on_snapshot(mock.Mock()) + # close should not be called again when already closing + inst.close.assert_not_called() + + def test_watch_on_snapshot_target_no_change_no_target_ids_not_current(): inst = _make_watch() proto = _make_listen_response()