Potential bug: SIGSEGV in Thin-mode AsyncConnection.fetch_df_batches() for VARCHAR2 + TIMESTAMP result; synchronous dataframe fetch succeeds
还没有人认领这个 Issue。
评估
调研方向
The crash occurs in the thin-mode async dataframe fetch path, specifically in AsyncConnection.fetch_df_batches() when a VARCHAR2 column is followed by a TIMESTAMP column. Start by examining the async dataframe fetching implementation in the oracledb source, focusing on type conversion and memory management. Reproduce the crash using the provided script to understand the exact point of failure, then compare with the synchronous fetch path to identify differences.
由索引模型根据 Issue 内容生成。
描述
1. Versions
-
python-oracledb: 26.0.1
-
Mode: Thin
-
Python: 3.14.7
-
PyArrow: 25.0.1
-
Platform: Linux 7.0.0-29-generic x86_64, glibc 2.41
-
64-bit Python: yes
-
OS family used by the application: Debian 13 or newer
-
init_oracle_client()is not called
2. Is this an error, hang, or crash?
Crash: the Python interpreter terminates with SIGSEGV, normally with exit
status 139.
No Python exception is raised.
3. Behavior
Thin-mode AsyncConnection.fetch_df_batches() segfaults while fetching a
result containing a VARCHAR2 column followed by a TIMESTAMP(6) column.
The crash occurs while advancing the async dataframe iterator, before the
returned object is converted with pyarrow.table().
The equivalent synchronous Connection.fetch_df_batches() call succeeds and
returns all rows.
Ordinary row fetching with AsyncCursor.fetchmany() also succeeds.
The two source columns are described as:
STATEMENTKEY:
type_code=DB_TYPE_VARCHAR
display_size=30
internal_size=30
precision=None
scale=None
null_ok=False
WRITETIME:
type_code=DB_TYPE_TIMESTAMP
display_size=23
internal_size=None
precision=0
scale=6
null_ok=True
For a representative 1,000-row result:
all 1,000 VARCHAR2 values are non-null;
all 1,000 TIMESTAMP values are non-null;
the VARCHAR2 column contains one distinct/repeated value;
the TIMESTAMP column contains 1,000 distinct values.
Isolation results:
Query shape
Async dataframe fetch
VARCHAR2 only
succeeds
NUMBER only
succeeds
TIMESTAMP only
succeeds
VARCHAR2 + NUMBER
succeeds
NUMBER + TIMESTAMP
succeeds
VARCHAR2 + TIMESTAMP
SIGSEGV
VARCHAR2 + CAST(TIMESTAMP AS TIMESTAMP(6))
succeeds in the reduced test
Same VARCHAR2 + TIMESTAMP query using synchronous Connection.fetch_df_batches()
succeeds
A synthetic DUAL CONNECT BY query with a repeated VARCHAR2 value and generated
TIMESTAMP values did not reproduce the crash. It may therefore depend on
additional result metadata or the exact encoded values.
This appears related to, but different from, issue #597:
the VARCHAR2 column has a defined internal_size of 30;
the failure was isolated to AsyncConnection.fetch_df_batches();
synchronous Connection.fetch_df_batches() succeeds.
4. Reproducer using an existing table
The following reproduces consistently against the affected view. The object and
column names below are anonymized, but the reported Oracle data types and
metadata are unchanged.
import asyncio
import faulthandler
import oracledb
import pyarrow as pa
faulthandler.enable()
USER = "..."
PASSWORD = "..."
DSN = "host:1521/service"
SQL = """
select varchar_key, timestamp_value
from affected_view
where rownum <= 1000
"""
async def reproduce_async():
async with oracledb.connect_async(
user=USER,
password=PASSWORD,
dsn=DSN,
) as connection:
batches = connection.fetch_df_batches(
statement=SQL,
size=1000,
fetch_decimals=True,
)
iterator = aiter(batches)
print("before async fetch", flush=True)
# The interpreter segfaults during this await. The next print is not
# reached, and pyarrow.table() is not involved in the crash.
oracle_dataframe = await anext(iterator)
print("after async fetch", flush=True)
table = pa.table(oracle_dataframe)
print(table.schema)
asyncio.run(reproduce_async())
Equivalent synchronous control:
import oracledb
import pyarrow as pa
with oracledb.connect(
user=USER,
password=PASSWORD,
dsn=DSN,
) as connection:
for oracle_dataframe in connection.fetch_df_batches(
statement=SQL,
size=1000,
fetch_decimals=True,
):
table = pa.table(oracle_dataframe)
print(table.schema, table.num_rows)
The synchronous control completes successfully.
Ordinary async row-fetch control:
import asyncio
import oracledb
async def row_fetch_control():
async with oracledb.connect_async(
user=USER,
password=PASSWORD,
dsn=DSN,
) as connection:
async with connection.cursor() as cursor:
cursor.arraysize = 1000
cursor.prefetchrows = 1000
await cursor.execute(SQL)
rows = await cursor.fetchmany(1000)
print(len(rows))
asyncio.run(row_fetch_control())
This also completes successfully.
5. Requested-schema behavior
The async crash was also observed in the application when passing a PyArrow
requested_schema, for example:
schema = pa.schema([
("VARCHAR_KEY", pa.string()),
("TIMESTAMP_VALUE", pa.timestamp("us")),
])
async for oracle_dataframe in connection.fetch_df_batches(
statement=SQL,
size=1000,
fetch_decimals=True,
requested_schema=schema,
):
table = pa.table(oracle_dataframe)
The crash still occurs while fetching, before the pa.table() call.
6. Expected behavior
AsyncConnection.fetch_df_batches() should return the same dataframe values as
the successful synchronous dataframe fetch, or raise a Python exception if the
result cannot be represented.
It should not terminate the interpreter.
- 主要语言
- Python
- 星标
- 454
- 派生
- 119
- PR 合并指标
- 30 天内没有已合并 PR
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
oracle/python-oracledb 的其他 Issue
-
asyncio: DPY-4011 on connect_async() when the listener closes the original socket after a redirect可能已有人在做 @AlexGracas 于 8 天前认领。 未关闭
难度 3/5 1-2 天 新手友好度 35/100
oracle/python-oracledb#616 ·
-
bug
难度 4/5 3-5 天 新手友好度 48/100
oracle/python-oracledb#615 ·
-
Fetch character columns as raw bytes in the database character set into data frames (Thick mode)未关闭enhancement
难度 5/5 一周以上 新手友好度 35/100
oracle/python-oracledb#614 · 1 条评论 ·
-
Client Library or Database
难度 4/5 3-5 天 新手友好度 35/100
oracle/python-oracledb#613 · 3 条评论 ·
-
enhancement
难度 5/5 一周以上 新手友好度 40/100
oracle/python-oracledb#612 ·
查看 oracle/python-oracledb 的全部 Issue
相似的 Issue
-
documentation pkg: sphinx-needs
难度 1/5 1 小时以内 新手友好度 82/100
useblocks/sphinx-needs#2255 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 60/100
home-assistant/core#186538 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100
btclib-org/btclib-secp256k1#1181 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 65/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
pyrite-wiki/pyrite#917 ·
维护者通常 1 天内回复