MagicStack / MagicStack/uvloop
_monitor_fs does not seem to hold reference to callback
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Cython
- Star
- 11.9k
- Fork
- 616
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Mô tả
uvloop version: 0.17.0
python version: 3.8.10
platform: linux
The bug can be reproduced with the below script. I call _monitor_fs on the loop, passing in a function callback that itself has a reference to the file I'm reading as well as the handle to the _monitor_fs. I set a timer to later call gc.collect and when that happens, my object gets deleted and I stop getting read events.
This does seem to be a bug because the loop itself should have reference to my callback which has a reference to my object and that object has a reference to the file and handle, so GC should not be collecting them.
import functools
import gc
import sys
import tempfile
import typing
import uvloop
import os.path
import subprocess
class FileAndHandle:
def __init__(self, f: typing.IO):
self.f = f
self.handle = None
def __del__(self):
print('goodbye cruel world')
class FileWatcher:
_proc: typing.Optional[subprocess.Popen]
def __init__(self):
self._loop = uvloop.new_event_loop()
self._proc = None
self._last_read_event = 0
def _do_read(self, file_and_handle: FileAndHandle, _os_fn: bytes, _ev_enum: int):
self._last_read_event = self._loop.time()
print(f'read: {repr(file_and_handle.f.read())}')
def _check_read_timer(self):
t = self._loop.time()
if t - self._last_read_event > 3:
print('stopped getting read events')
self._proc.kill()
self._loop.stop()
else:
self._loop.call_later(1, self._check_read_timer)
def _start_watching(self, f_path: str) -> None:
fah = FileAndHandle(open(f_path))
fah.handle = self._loop._monitor_fs(f_path, functools.partial(self._do_read, fah))
def main(self) -> None:
with tempfile.TemporaryDirectory() as tmp_dir:
pth = os.path.join(tmp_dir, "file.txt")
open(pth, 'wt').close()
self._proc = subprocess.Popen([sys.executable, '-c', f'''
import time
with open("{pth}", "wt") as f:
while True:
time.sleep(2)
f.write("hello\\n")
f.flush()
'''])
self._start_watching(pth)
self._loop.call_later(3, self._check_read_timer)
self._loop.call_later(15, gc.collect)
self._loop.run_forever()
if __name__ == '__main__':
FileWatcher().main()
Hướng dẫn đóng góp
Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Chạy reproducer được cung cấp và quan sát xem các sự kiện có dừng lại sau gc.collect hay không. Sau đó, lần theo điểm vào _monitor_fs và cách xử lý callback của nó; công việc được xem là hoàn tất khi callback và FileAndHandle mà nó tham chiếu vẫn có thể sử dụng được, đồng thời các sự kiện đọc tiếp tục sau khi garbage collection.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- linux, python
- Lĩnh vực
- backend, operating-systems
- Loại issue
- Lỗi
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 35/100