deepkilo commented on issue #50482:
URL: https://github.com/apache/arrow/issues/50482#issuecomment-6245996306

   Additional Linux evidence from compatibility testing of a 
quantitative-research runtime. This was an observed process-exit failure 
investigated back to native cleanup, not a finding from source review alone. 
Our reproducer uses generated files and a Python filesystem wrapper; it is 
related evidence, not a claim that every file-object case has exactly the same 
ownership path.
   
   With official PyArrow 26, a malformed fragment raises the expected 
`ArrowInvalid`, but the process can still fail during interpreter shutdown. On 
Linux x86_64 our reduced case aborted on CPython 3.12.15 (12/12 four-fragment 
runs and 12/12 eight-fragment runs), timed out on 3.13.16 (4/4), and also timed 
out on unmodified 26 with 3.15.0 (3/3). Upgrading Python alone did not repair 
it.
   
   Self-contained reduced case; run in fresh processes with a timeout, since 
the symptom is at exit:
   
   ```python
   import tempfile
   from pathlib import Path
   import fsspec
   import pyarrow as pa
   import pyarrow.dataset as ds
   import pyarrow.fs as fs
   import pyarrow.parquet as pq
   
   root = Path(tempfile.mkdtemp())
   pq.write_table(pa.table({'value': [1, 2, 3]}), root / 'valid.parquet')
   (root / 'bad.parquet').write_bytes(b'not a parquet file')
   filesystem = fs.PyFileSystem(fs.FSSpecHandler(fsspec.filesystem('file')))
   paths = [str(root / name) for name in
            ['valid.parquet', 'bad.parquet', 'valid.parquet', 'valid.parquet']]
   dataset = ds.dataset(paths, filesystem=filesystem, format='parquet',
                        schema=pa.schema([('value', pa.int64())]),
                        exclude_invalid_files=False)
   try:
       dataset.to_table(use_threads=True, fragment_readahead=4)
   except pa.ArrowInvalid:
       pass
   else:
       raise AssertionError('Expected the malformed-fragment error')
   ```
   
   Our captured native stack passes through callback-capture destruction, 
`MergedGenerator` / `SerialReadahead`, the Parquet reader / `ReadRangeCache`, 
and `PyBuffer::~PyBuffer`, then `PyGILState_Ensure` during `Py_FinalizeEx`. On 
3.12 the forced unwind crosses a noexcept boundary and terminates; newer Python 
parks the late worker while Arrow's pool shutdown joins it.
   
   This also relates to #46945: checking `Py_IsInitialized` or finalization 
before acquiring the GIL leaves a check-to-acquire race. A local candidate uses 
Python 3.15's PEP 788 view/token admission API for `PyBuffer`, `NumPyBuffer`, 
and `OwnedRefNoGIL` cleanup. The complete Python-native wheel was rebuilt, with 
the eight computational Arrow/Parquet DSOs retained byte-for-byte. Eighteen 
bounded subprocess checks then exited normally, including malformed-input and 
valid-input controls; the malformed fragment still raises rather than being 
suppressed.
   
   That candidate is qualified only for main-interpreter, GIL CPython 3.15, not 
older Python, free-threaded builds or subinterpreters. A failed admission can 
also mean allocation failure, so the candidate's skipped cleanup may leak a 
reference in that case. I am sharing the mechanism and verification boundary 
for discussion, not claiming a universally ready upstream fix or a newly 
introduced 26 regression.
   
   Disclosure: OpenAI Codex (GPT-6 family; exact variant/effort unavailable in 
this session) assisted with investigation, tool-driven reproduction, candidate 
work and this text. The stated runs and native stacks are recorded execution 
evidence, not a claim that the operator manually performed or reviewed every 
step. No maintainer ping or competing PR is intended.
   


-- 
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