Skip to content

Commit 5f06377

Browse files
committed
fix(core): send cache_invalidate events before and after locking to avoid deadlocks
1 parent ccc5faf commit 5f06377

File tree

1 file changed

+17
-11
lines changed

1 file changed

+17
-11
lines changed

packages/core/src/robotcode/core/text_document.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
import inspect
33
import io
44
import weakref
5+
from contextlib import contextmanager
56
from typing import (
67
Any,
78
Callable,
89
Dict,
910
Final,
11+
Iterator,
1012
List,
1113
Optional,
1214
TypeVar,
@@ -143,25 +145,23 @@ def revert(self, version: Optional[int]) -> bool:
143145

144146
@_logger.call
145147
def apply_none_change(self) -> None:
146-
with self._lock:
148+
with self._cache_invalidating():
147149
self._lines = None
148-
self._invalidate_cache()
149150

150151
@_logger.call
151152
def apply_full_change(self, version: Optional[int], text: Optional[str], *, save: bool = False) -> None:
152-
with self._lock:
153+
with self._cache_invalidating():
153154
if version is not None:
154155
self._version = version
155156
if text is not None:
156157
self._text = text
157158
self._lines = None
158159
if save:
159160
self._orig_text = self._text
160-
self._invalidate_cache()
161161

162162
@_logger.call
163163
def apply_incremental_change(self, version: Optional[int], range: Range, text: str) -> None:
164-
with self._lock:
164+
with self._cache_invalidating():
165165
try:
166166
if version is not None:
167167
self._version = version
@@ -193,7 +193,6 @@ def apply_incremental_change(self, version: Optional[int], range: Range, text: s
193193
self._text = new_text.getvalue()
194194
finally:
195195
self._lines = None
196-
self._invalidate_cache()
197196

198197
def __get_lines(self) -> List[str]:
199198
if self._lines is None:
@@ -214,13 +213,21 @@ def cache_invalidate(sender) -> None: ...
214213
@event
215214
def cache_invalidated(sender) -> None: ...
216215

216+
@contextmanager
217+
def _cache_invalidating(self) -> Iterator[None]:
218+
self.cache_invalidate()
219+
try:
220+
with self._lock:
221+
yield
222+
finally:
223+
self._invalidate_cache()
224+
self.cache_invalidated(self)
225+
217226
def _invalidate_cache(self) -> None:
218-
self.cache_invalidate(self)
219227
self._cache.clear()
220-
self.cache_invalidated(self)
221228

222229
def invalidate_cache(self) -> None:
223-
with self._lock:
230+
with self._cache_invalidating():
224231
self._invalidate_cache()
225232

226233
def _invalidate_data(self) -> None:
@@ -288,12 +295,11 @@ def get_data(self, key: Any, default: Optional[Any] = None) -> Any:
288295

289296
def _clear(self) -> None:
290297
self._lines = None
291-
self._invalidate_cache()
292298
self._invalidate_data()
293299

294300
@_logger.call
295301
def clear(self) -> None:
296-
with self._lock:
302+
with self._cache_invalidating():
297303
self._clear()
298304

299305
def position_from_utf16(self, position: Position) -> Position:

0 commit comments

Comments
 (0)