fix: run all HBaseIO cleanup steps even if an earlier close() throws [fj4WqyCCw3C5ShR1RfB7MoBPTpkRrBFYP1uT35g3MvT] - #39711
Conversation
…rlier close() throws
|
@waterWang heads-up on an overlap, and an offer. I filed #39710 and then opened #39712 for it without re-checking — yours went up ten minutes before mine and I simply missed it. That's on me. Yours is first on the clock and the fix reads correct to me: same three sites, same "run every step, keep the first failure, suppress the rest" shape, and you got the The one thing yours doesn't have is tests, and CI is currently showing 2 failures. Mine carries
Reverting each teardown one at a time fails exactly and only its own test, so they're pinned per-site rather than as a block. You're welcome to take that file wholesale — it's at No ownership claim here, I'd just like the fix to land with coverage. |
|
Checks are failing. Will not request review until checks are succeeding. If you'd like to override that behavior, comment |
Fixes #39710
What
HBaseIOreleases its resources as consecutive, unguarded statements in three teardown paths. If an earlierclose()throws, everything after it is skipped:HBaseReader.close()— a throwingscanner.close()leaks theConnection.HBaseWriterFn.tearDown()—BufferedMutator.close()is documented to throw on a final flush failure (down region server, network blip), so a failed flush skipsconnection.close(), leaking the whole per-@SetupConnection.HBaseRowMutationWriterFn.tearDown()— worst case: a throwingtable.close()skipsHBaseSharedConnection.close(configuration), which is a reference-count decrement. Because the pool is astatic HashMap, the leaked entry (and its ZooKeeper session / RPC threads) survives for the JVM lifetime and every latergetOrCreatehands back the same permanently-unreleasable connection.Fix
Wrap each cleanup step in
try/finallyso every step runs unconditionally, while preserving the first failure and attaching later ones withaddSuppressed, so callers still see the error that actually broke the job rather than a teardown symptom.HBaseReader.close(): connection is now always closed even ifscanner.close()throws.HBaseWriterFn.tearDown():connection.close()always runs even ifmutator.close()throws.HBaseRowMutationWriterFn.tearDown():HBaseSharedConnection.close(configuration)(the refcount decrement) always runs even iftable.close()throws.Testing
Existing tests in
sdks/java/io/hbase/src/test/java/org/apache/beam/sdk/io/hbase/cover the read and write paths; the change is purely control-flow (guarding cleanup), so no new behavior is introduced when nothing throws.