Skip to content

Give cursors a PEP 249 closed state and make query and session starts interrupt-safe #1207

Closed

Description

@laughingman7743

Part of #1205 (step 3; see R3 and model 3 there).

Problem

  1. Closed cursors keep working. close() (pyathena/result_set.py:1328-1332) closes the result set but does not mark the cursor closed. Fetches after close() return None / [], and execute() works again. PEP 249 says a closed cursor raises an Error for any operation. The sync and asyncio cursors behave the same.
  2. Interrupt before polling. A KeyboardInterrupt in the sync on_start_query_execution callback (pyathena/cursor.py:187) is raised before _poll(). kill_on_interrupt therefore never sends StopQueryExecution, and the query keeps running.
  3. cancel() races. Out of scope: a cancel() from another thread on the same cursor is unsupported under threadsafety = 2, as decided in Break result sets after failed or cancelled fetches and drop the cross-thread close guards #1206. The documentation example that does it is rewritten in the Break result sets after failed or cancelled fetches and drop the cross-thread close guards #1206 PR.
  4. Spark session leak. StartSession catches only Exception (pyathena/spark/common.py:256-265). A KeyboardInterrupt during or after the request leaves the session running, while the calculation start is interrupt-safe.

Reproduction

The stub reproductions are summarized in #1205. They use stubbed Athena clients and no AWS calls.

Environment

  • PyAthena master at b2d7aa2
  • Python 3.15

Proposed fix (optional)

  • Give cursors a closed state. execute(), executemany(), and the fetch methods of a closed cursor raise ProgrammingError, as PEP 249 requires. This is a breaking change for callers that reuse a closed cursor, and the release notes will call it out. A close() from another thread during execute() is unsupported and not handled.
  • Start the protected region of kill_on_interrupt once the execution ID exists, so that the start callback is inside it.
  • Give the Spark StartSession the same interrupt-safe start as calculations.

Validate with unit tests for the sync, AsyncCursor, asyncio, and Spark cursors.

Activity

  1. changed the title [-]Give cursors a PEP 249 closed state and make query starts and cancel() interrupt-safe[/-] [+]Give cursors a PEP 249 closed state and make query and session starts interrupt-safe[/+] on Oct 17, 2026
  2. added a commit that references this issue on Oct 18, 2026
    45f9104
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions