Skip to content

Core: Restore the interrupt status in JdbcCatalog.execute - #17492

Open
PDGGK wants to merge 1 commit into
apache:mainfrom
PDGGK:fix-jdbc-catalog-interrupt-status
Open

Core: Restore the interrupt status in JdbcCatalog.execute#17492
PDGGK wants to merge 1 commit into
apache:mainfrom
PDGGK:fix-jdbc-catalog-interrupt-status

Conversation

@PDGGK

@PDGGK PDGGK commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

JdbcCatalog has four InterruptedException handlers. Three of them restore the interrupt status before rethrowing; execute does not.

restores
initializeCatalogTables (:227) yes
updateSchemaIfRequired (:268) yes
execute (:781) no
fetch (:814) yes

execute backs every write path — dropTable, renameTable, renameView, dropNamespace and the namespace property insert/update/delete — so a task cancelled while waiting for a pooled connection ends up with a thread whose interrupt status has been cleared by Object.wait. Anything downstream that polls Thread.interrupted() to decide whether to stop, including the executors Spark and Flink use to cancel work, sees a thread that was never interrupted.

The fix is the same one line the other three handlers already have.

Testing

TestJdbcCatalog.testExecuteRestoresInterruptStatus builds a catalog with clients=1, holds the single pooled connection from another thread through the existing @VisibleForTesting connectionPool() accessor, interrupts the test thread, and asserts that dropTable both throws UncheckedInterruptedException and leaves the interrupt status set. It fails on main with Expecting value to be true but was false and passes with this change. Two latches rather than sleeps, so there is no timing window.

One thing worth flagging for whoever reviews the test: it has to call dropTable(ident, false). The single-argument dropTable defaults to purge = true, which reads table metadata through fetch first — and fetch already restores the status, so the assertion would pass even without the fix. The same trap applies to dropNamespace and the property setters.

  • :iceberg-core:test --tests "org.apache.iceberg.jdbc.*" — passes
  • :iceberg-core:spotlessCheck — passes

@github-actions github-actions Bot added the core label Aug 3, 2026
Thread.currentThread().interrupt();
// purge = false keeps this on the execute() path. The default purge = true would first
// read table metadata through fetch(), which already restores the interrupt status.
assertThatThrownBy(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assert has no .hasMessage(...) / .hasMessageContaining(...) assertion. Iceberg's checkstyle rule AssertThatThrownByWithMessageCheck requires a message check on every assertThatThrownBy chain.

execute() is the only one of the four InterruptedException handlers in
JdbcCatalog that rethrows without calling Thread.currentThread().interrupt();
initializeCatalogTables, updateSchemaIfRequired and fetch all restore it.

execute() backs every write path - dropTable, renameTable, renameView,
dropNamespace and the namespace property insert/update/delete - so a task
cancelled while waiting for a pooled connection loses the interrupt status
and any caller that checks it afterwards sees a thread that was never
interrupted.
@PDGGK
PDGGK force-pushed the fix-jdbc-catalog-interrupt-status branch from 8aacaaf to 85c9952 Compare August 3, 2026 12:11
@PDGGK

PDGGK commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Good catch, thanks — fixed in 85c9952, the assertion now chains .hasMessage("Interrupted in SQL command"), matching how the rest of this file asserts (listNamespaces at :203, listViews at :305).

That was my miss: I ran spotlessCheck locally but not checkstyleTest, so the rule never had a chance to fire. I confirmed it does catch it — removing the .hasMessage(...) again reproduces your finding exactly:

[ant:checkstyle] [ERROR] .../jdbc/TestJdbcCatalog.java:1335: assertThatThrownBy must include a message check like .hasMessage(...) [AssertThatThrownByWithMessageCheck]

:iceberg-core:checkstyleMain, :iceberg-core:checkstyleTest and the test itself are all green on the new head.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants