Race in `inner_timout_checker`: iterating over `m.start_time_by_pid.items()` can crash with "dictionary changed size during iteration" and leave `mutmut run` hanging

Đang mở
#490 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
52/100
Loại issue
Lỗi
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Ít trao đổi
Công nghệ
python
Lĩnh vực
testing-qa, tooling

Hướng nghiên cứu

Bắt đầu tại entry point inner_timout_checker trong main.py, xung quanh iteration được báo cáo, và theo dõi các cập nhật đối với start_time_by_pid trong khi chạy mutmut run. Tái hiện bằng Python 3.10 với python3.10 -m mutmut run, sau đó kiểm tra việc điều phối worker và phạm vi bao phủ pytest hiện có. Được xem là hoàn tất khi race không còn làm checker bị crash và command không bị treo với các worker còn sót lại.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Command

python3.10 -m mutmut run

Observed behavior

During mutation testing, mutmut prints this exception from the timeout-checker background thread:

Exception in thread Thread-1061 (inner_timout_checker):
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 953, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/pomponchik/Desktop/Projects/suby/.venv/lib/python3.8/site-packages/mutmut/__main__.py", line 1201, in inner_timout_checker
    for pid, start_time in m.start_time_by_pid.items():
RuntimeError: dictionary changed size during iteration

After that, mutmut run appears to hang indefinitely.

I checked the process tree, and the parent python -m mutmut run process plus multiple worker python -m mutmut run children were still alive, but all of them were sleeping at 0.0% CPU. So it looks like once inner_timout_checker crashes, the main orchestration can get stuck forever instead of failing and cleaning up workers.

Expected behavior

inner_timout_checker should not iterate over a dict that can be concurrently mutated without synchronization/copying. And if a background orchestration thread crashes anyway, mutmut run should fail loudly and terminate workers instead of hanging.

Why this looks like a race

The failing line iterates directly over:

for pid, start_time in m.start_time_by_pid.items():

The exception strongly suggests that some other thread mutates m.start_time_by_pid at the same time.

So a minimal fix might be to iterate over a snapshot, e.g. list(m.start_time_by_pid.items()), or guard access with a lock, depending on the intended synchronization model.

Extra note

I first tried running mutmut from a Python 3.8 venv and hit a separate issue:

AttributeError: module 'os' has no attribute 'waitstatus_to_exitcode'

So the hang above was reproduced by running mutmut itself with Python 3.10.8.

Environment

  • mutmut: 3.2.3
  • OS: macOS 15.3.1 (24D70)
  • Python used to run mutmut: 3.10.8
  • Test runner: pytest
  • Project size: ~245 mutants
Ngôn ngữ chính
Python
Star
1.5k
Fork
190
Merge trung bình
1 ngày 11 giờ
Pull request đã merge (30 ngày)
8

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. 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.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của boxed/mutmut

Tất cả issue của boxed/mutmut

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.