Skip to content

Commit c903cfa

Browse files
authored
Merge pull request #6 from ngoldbaum/fix-deadlock4
Fix deadlock4
2 parents a8772e2 + c94854a commit c903cfa

File tree

2 files changed

+19
-3
lines changed

2 files changed

+19
-3
lines changed

src/watchdog/observers/winapi.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,12 @@ def _generate_observed_path_deleted_event() -> tuple[bytes, int]:
293293
return buff.raw, event_size
294294

295295

296+
OPEN_HANDLES = set()
297+
298+
296299
def get_directory_handle(path: str) -> HANDLE:
297300
"""Returns a Windows handle to the specified directory path."""
298-
return CreateFileW(
301+
handle = CreateFileW(
299302
path,
300303
FILE_LIST_DIRECTORY,
301304
WATCHDOG_FILE_SHARE_FLAGS,
@@ -304,9 +307,16 @@ def get_directory_handle(path: str) -> HANDLE:
304307
WATCHDOG_FILE_FLAGS,
305308
None,
306309
)
310+
OPEN_HANDLES.add(handle)
311+
return handle
307312

308313

309314
def close_directory_handle(handle: HANDLE) -> None:
315+
try:
316+
OPEN_HANDLES.remove(handle)
317+
except KeyError:
318+
# another thread already closed the handle
319+
return
310320
try:
311321
CancelIoEx(handle, None) # force ReadDirectoryChangesW to return
312322
CloseHandle(handle)

tests/conftest.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import contextlib
4+
import faulthandler
45
import gc
56
import os
67
import threading
@@ -27,10 +28,15 @@ def _no_thread_leaks():
2728
We do not use pytest-threadleak because it is not reliable.
2829
"""
2930
old_thread_count = threading.active_count()
31+
3032
yield
31-
gc.collect() # Clear the stuff from other function-level fixtures
32-
assert threading.active_count() == old_thread_count # Only previously existing threads
3333

34+
# Clear the stuff from other function-level fixtures
35+
gc.collect()
36+
37+
# Only previously existing threads, allowing for threads that were
38+
# being cleaned up while this test was starting
39+
assert threading.active_count() <= old_thread_count
3440

3541
@pytest.fixture(autouse=True)
3642
def _no_warnings(recwarn):

0 commit comments

Comments
 (0)