Skip to content

Fix closeOnCompletion() infinite recursion on ResultSet/Statement close (ES-1978361)#1493

Open
sreekanth-db wants to merge 1 commit into
databricks:mainfrom
sreekanth-db:fix/es-1978361-closeoncompletion-recursion
Open

Fix closeOnCompletion() infinite recursion on ResultSet/Statement close (ES-1978361)#1493
sreekanth-db wants to merge 1 commit into
databricks:mainfrom
sreekanth-db:fix/es-1978361-closeoncompletion-recursion

Conversation

@sreekanth-db

Copy link
Copy Markdown
Collaborator

Summary

Fixes ES-1978361: with Statement.closeOnCompletion() enabled, closing the ResultSet (or Statement) recursed infinitely between ResultSet.close() and Statement.close(), producing a StackOverflowError that surfaced to users as an indefinite hang after a successful query (thread blocked in the SSL socket read of a half-torn-down operation, statement.isClosed() stuck false).

Root cause

closeOnCompletion() creates a mutual-recursion cycle with no idempotency guard:

  1. Statement.close() closes its ResultSet.
  2. ResultSet.close() calls back into Statement.handleResultSetClose().
  3. Because closeOnCompletion is set, that calls Statement.close() again → step 1.

ResultSet.close() had no "already closed" check, so the cycle never terminated.

Fix

Make ResultSet.close() idempotent: return early if already closed, and set isClosed before notifying the parent Statement, so the re-entrant close triggered via handleResultSetClose() short-circuits at the guard. Minimal, targeted change; no behavior change on the normal close path.

Testing

  • Two regression tests (DatabricksStatementTest) covering both entry points — ResultSet.close() and Statement.close() — with closeOnCompletion() enabled. Verified they fail with StackOverflowError without the fix and pass with it.
  • Full DatabricksStatementTest + DatabricksResultSetTest (185 tests) pass.
  • Verified against a live SQL warehouse: query runs, rs.close() completes promptly, rs.isClosed() and stmt.isClosed() both true, no crash.

This pull request and its description were written by Isaac.

ResultSet.close() and Statement.close() recursed into each other
indefinitely when closeOnCompletion() was enabled, causing a
StackOverflowError / apparent hang after a successful query.

Make ResultSet.close() idempotent: return early if already closed, and
set isClosed before notifying the parent Statement so the re-entrant
close triggered via handleResultSetClose() short-circuits at the guard.

Adds regression tests for both entry points (ResultSet.close() and
Statement.close()) with closeOnCompletion() enabled.

Co-authored-by: Isaac
Signed-off-by: Sreekanth Vadigi <sreekanth.vadigi@databricks.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant