From 4dc426000d35a93ee0681c0c0124d4b1d3c53ad8 Mon Sep 17 00:00:00 2001 From: gaozhangmin Date: Fri, 15 Oct 2021 08:23:22 +0800 Subject: [PATCH] Heap memory leak problem when ledger replication failed (#2794) ### Motivation production environment, memory leak always happened, and there were ledger cannot be replicated successfully. This cause by when `openLedgerNoRecovery` with `BKNotEnoughBookiesException`, the LedgerHandler won't closed properly, caused memory leak https://github.com/apache/bookkeeper/blob/c7236adc3cb659e65ae5ce53b7156569d7f50ebd/bookkeeper-server/src/main/java/org/apache/bookkeeper/replication/ReplicationWorker.java#L364-L424 ### Changes close LedgerHandler when openComplete with exception --- .../apache/bookkeeper/client/LedgerOpenOp.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerOpenOp.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerOpenOp.java index 2193b3ef9fb..e74fcb62144 100644 --- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerOpenOp.java +++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerOpenOp.java @@ -129,6 +129,19 @@ public void initiateWithoutRecovery() { initiate(); } + private void closeLedgerHandle() { + try { + if (lh != null) { + lh.close(); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + LOG.info("InterruptedException while closing ledger {}", ledgerId, e); + } catch (BKException e) { + LOG.warn("BKException while closing ledger {} ", ledgerId, e); + } + } + private void openWithMetadata(Versioned versionedMetadata) { LedgerMetadata metadata = versionedMetadata.getValue(); @@ -196,8 +209,10 @@ public void safeOperationComplete(int rc, Void result) { if (rc == BKException.Code.OK) { openComplete(BKException.Code.OK, lh); } else if (rc == BKException.Code.UnauthorizedAccessException) { + closeLedgerHandle(); openComplete(BKException.Code.UnauthorizedAccessException, null); } else { + closeLedgerHandle(); openComplete(bk.getReturnRc(BKException.Code.LedgerRecoveryException), null); } } @@ -212,6 +227,7 @@ public String toString() { public void readLastConfirmedComplete(int rc, long lastConfirmed, Object ctx) { if (rc != BKException.Code.OK) { + closeLedgerHandle(); openComplete(bk.getReturnRc(BKException.Code.ReadException), null); } else { lh.lastAddConfirmed = lh.lastAddPushed = lastConfirmed;