XiaoHongbo-Hope opened a new pull request, #9267:
URL: https://github.com/apache/paimon/pull/9267

   ## What
   
   Follow-up to #9250. The concurrent-import fix added a `threading.RLock` 
around `importlib.import_module()` in three package `__init__`s (`pypaimon`, 
`pypaimon.tag`, `pypaimon.globalindex`) to serialize lazy resolution. That lock 
introduced a **new** deadlock path, flagged as P1 in the #9250 review.
   
   ## Why the lock deadlocks
   
   Production code does top-level `from pypaimon import Schema` (e.g. 
`pypaimon/multimodal/connection.py`). With the root RLock in place:
   
   - Thread A holds the root RLock, then imports a leaf module → waits on that 
leaf's module lock.
   - Thread B holds the leaf module lock (importing the leaf directly), then 
resolves a top-level export → waits on the root RLock.
   
   Classic lock-ordering inversion → `_DeadlockError` / `partially initialized 
module` on concurrent cold-start imports (new Ray workers, parallel split 
deserialization). Probabilistic, so CI easily misses it.
   
   ## Fix
   
   Remove all three custom locks. Once the eager-init cycles are broken, 
Python's own per-module import locks make `import_module` thread-safe and 
idempotent, and the `globals()` assignment is atomic — the extra lock was both 
redundant and the source of the new deadlock.
   
   Removing the locks alone re-surfaces deadlocks in two more packages whose 
eager sibling imports were previously masked by the lock, so those are also 
converted to lazy `__getattr__`:
   
   - `pypaimon.data` — lazy `__getattr__` (was 3/200 without it)
   - `pypaimon.common.options` — lazy `__getattr__`, plus break the 
`core_options`/`options` self-cycles via direct module imports (the package is 
imported by name from many modules its own eager exports pull in)
   
   ## Test
   
   New regression `test_concurrent_leaf_imports_and_top_level_export` races 
leaf imports (`DataFileMeta`, `SimpleStats`, `query_auth_split`, 
`index_file_meta`, `table_delete`, `multimodal.connection`) against top-level 
exports (`Schema`, `CatalogFactory`) across 8 fresh processes with a 1e-6 
switch interval.
   
   ## Stress (8-way, 400 fresh processes)
   
   | | failures |
   |---|---|
   | master (#9250, with root lock) | 115/400 |
   | this PR | 0/400 |
   
   Master failures deadlock on 
`_ModuleLock('pypaimon.common.options.core_options')` — the exact cycle broken 
by the `common.options` lazy conversion.
   
   ## Verification
   
   - `concurrent_import_test` + schema/options suite: 76 passed
   - flake8 (`dev/cfg.ini`): clean
   - Broad suite: 3661 passed, 63 skipped. The 13 failed / 14 collection errors 
are all missing optional deps (`lance`, `mosaic`, `ray`, `parameterized`, 
`_datasketches`, zstd) — confirmed identical on master.
   
   Draft until CI confirms.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to