6
0
mirror of https://github.com/FirebirdSQL/firebird-qa.git synced 2025-01-22 13:33:07 +01:00

Added/Updated tests\bugs\core_2477_test.py: Resultset of cursor that executes using instance of selectable PreparedStatement must be stored in some variable in order to have ability close it EXPLICITLY, before PS will be freed. Otherwise access violation can raises when Python runs garbage collection.

This commit is contained in:
pavel-zotov 2025-01-18 18:10:43 +03:00
parent 32b76b2e58
commit 028bb33780

View File

@ -23,18 +23,28 @@ FBTEST: bugs.core_2477
NOTES:
[16.11.2021] pcisar
This test is too complicated and fragile, and it's IMHO not worth to be implemented
[24.07.2022] pzotov
Test was totally re-implemented. No async call of ISQL, waiting/killing etc.
Checked on Windows: 3.0.8.33535 (SS/CS), 4.0.1.2692 (SS/CS), 5.0.0.591
Checked on Linux: 4.0.1.2692 (SS/CS) - needed to increase number of rows to be sorted.
[18.01.2025] pzotov
Resultset of cursor that executes using instance of selectable PreparedStatement must be stored
in some variable in order to have ability close it EXPLICITLY (before PS will be freed).
Otherwise access violation raises during Python GC and pytest hangs at final point (does not return control to OS).
This occurs at least for: Python 3.11.2 / pytest: 7.4.4 / firebird.driver: 1.10.6 / Firebird.Qa: 0.19.3
The reason of that was explained by Vlad, 26.10.24 17:42 ("oddities when use instances of selective statements").
"""
import subprocess
from pathlib import Path
from firebird.driver import DatabaseError
import time
import pytest
from firebird.qa import *
import time
init_script = """
create or alter view v_mon as
@ -108,6 +118,9 @@ def test_1(act: Action, capsys):
with act.db.connect() as con_worker:
cur_worker = con_worker.cursor()
cur_wrk_ps, cur_wrk_rs = None, None
try:
cur_wrk_ps = cur_worker.prepare(heavy_sql_sttm)
for m in ('beg','end'):
@ -121,7 +134,15 @@ def test_1(act: Action, capsys):
assert map_result.get(m), f"No rows returned from v_gather_mon for m='{m}'"
if m == 'beg':
cur_worker.execute(cur_wrk_ps)
# ::: NB ::: 'ps' returns data, i.e. this is SELECTABLE expression.
# We have to store result of cur.execute(<psInstance>) in order to
# close it explicitly.
# Otherwise AV can occur during Python garbage collection and this
# causes pytest to hang on its final point.
# Explained by hvlad, email 26.10.24 17:42
cur_wrk_rs = cur_worker.execute(cur_wrk_ps)
for i in range(0, ROWS_TO_BE_SORTED):
r = cur_worker.fetchone()
@ -130,6 +151,15 @@ def test_1(act: Action, capsys):
# We can now gather mon$ info second time (in a NEW connection)
# and then evaluate DIFFERENCE.
except DatabaseError as e:
print( e.__str__() )
print(e.gds_codes)
finally:
if cur_wrk_rs:
cur_wrk_rs.close() # <<< EXPLICITLY CLOSING CURSOR RESULTS
if cur_wrk_ps:
cur_wrk_ps.free()
#------------------------------------------------------------------------------------------
assert map_result['beg'][0].strip() == 'idle' and map_result['end'][0].strip() == 'stalled'