Skip to content

fix(python): share per-object locks and align StartChild timeouts - #5035

Merged
dbrattli merged 6 commits into
mainfrom
fix/python-lock-stripes
Oct 4, 2026
Merged

dbrattli merged 6 commits into
mainfrom
fix/python-lock-stripes

Conversation

@dbrattli

@dbrattli dbrattli commented Oct 3, 2026 •

Copy link
Copy Markdown
Collaborator

Concurrent F# lock calls on the same object currently create separate Python RLock instances, allowing their critical sections to overlap. Async.StartChild also raises Python's built-in TimeoutError instead of .NET's TimeoutException when its deadline expires.

Changes

  • Share a reentrant lock per object identity through a WeakValueDictionary. A short registry guard makes lookup and creation atomic and is released before acquiring the object lock or running user code. Holders and waiters retain their selected lock; unused entries are reclaimed without retaining the locked objects. Identity keys support unhashable and non-weak-referenceable objects.
  • Use the existing start_child entry point for both F# and Python callers. Deadline expiry raises TimeoutException, whose native base from merged feat(python): give System exceptions native Python bases #5040 preserves Python except TimeoutError handlers. Remove the separate start_child_with_timeout entry point and compiler special case.
  • Preserve the exact child exception object, including child-raised Python TimeoutError and .NET TimeoutException. Only cancellation caused by deadline expiry is translated.
  • Exercise locking through generated F# tests covering exclusion, independent objects, reentrancy, return values, exception release, and storage reclamation. Add timeout and child-failure regressions in tests/Python/TestAsync.fs; await their completion so failures reach the runner. Remove the standalone timeout test and its build-copy step.

Validation

  • Full repository Python gate with a freshly generated runtime: 2,403 .NET tests and 2,504 generated Python tests passed on Python 3.14.
  • Full generated Pyright remains at the existing 34 errors / 45 warnings baseline.
  • Restoring stripe-based identity mapping in an isolated process makes the independence regression fail. The original timeout handler also fails the child-exception identity probes.
  • Source Fantomas, changed timeout runtime Ruff lint/format, commit hooks, and git diff --check passed. Repository Fantomas policy excludes tests/**.
  • The Python run emitted the existing async timer-thread warning (Event loop is closed) and generated syntax warning.

@dbrattli
dbrattli marked this pull request as ready for review October 3, 2026 20:12
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Python Type Checking Results (Pyright)

Metric Value
Total errors 34
Files with errors 4
Excluded files 4
New errors ✅ No
Excluded files with errors (4 files)

These files have known type errors and are excluded from CI. Remove from pyrightconfig.ci.json as errors are fixed.

File Errors Status
temp/tests/Python/test_hash_set.py 18 Excluded
temp/tests/Python/test_applicative.py 12 Excluded
temp/tests/Python/test_nested_and_recursive_pattern.py 2 Excluded
temp/tests/Python/fable_modules/thoth_json_python/encode.py 2 Excluded

@dbrattli dbrattli changed the title fix(python): share bounded reentrant lock stripes fix(python): share per-object locks and align StartChild timeouts Oct 4, 2026
@dbrattli
dbrattli merged commit 2da7144 into main Oct 4, 2026
44 checks passed
@dbrattli
dbrattli deleted the fix/python-lock-stripes branch October 4, 2026 12:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant