From 426cd15e8c2ce8191fb13e0b5852e752f6a0260b Mon Sep 17 00:00:00 2001 From: dennis zhuang Date: Tue, 23 Nov 2021 15:34:29 +0800 Subject: [PATCH] (fix) Call NodeImpl#join asynchronously after shutting down node, #715, #718 (#722) --- .../com/alipay/sofa/jraft/core/NodeImpl.java | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/jraft-core/src/main/java/com/alipay/sofa/jraft/core/NodeImpl.java b/jraft-core/src/main/java/com/alipay/sofa/jraft/core/NodeImpl.java index 3f80f6d17..d7a395eb9 100644 --- a/jraft-core/src/main/java/com/alipay/sofa/jraft/core/NodeImpl.java +++ b/jraft-core/src/main/java/com/alipay/sofa/jraft/core/NodeImpl.java @@ -315,7 +315,7 @@ public void onEvent(final LogEntryAndClosure event, final long sequence, final b } private void reset() { - for (final LogEntryAndClosure task : tasks) { + for (final LogEntryAndClosure task : this.tasks) { task.reset(); } this.tasks.clear(); @@ -2731,7 +2731,7 @@ public boolean isLeader(final boolean blocking) { } @Override - public void shutdown(final Closure done) { + public void shutdown(Closure done) { List timers = null; this.writeLock.lock(); try { @@ -2785,16 +2785,10 @@ public void shutdown(final Closure done) { if (this.state != State.STATE_SHUTDOWN) { if (done != null) { this.shutdownContinuations.add(done); + done = null; } return; } - - // This node is down, it's ok to invoke done right now. Don't invoke this - // in place to avoid the dead writeLock issue when done.Run() is going to acquire - // a writeLock which is already held by the caller - if (done != null) { - Utils.runClosureInThread(done); - } } finally { this.writeLock.unlock(); @@ -2802,6 +2796,23 @@ public void shutdown(final Closure done) { if (timers != null) { destroyAllTimers(timers); } + // Call join() asynchronously + final Closure shutdownHook = done; + Utils.runInThread(() -> { + try { + join(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } finally { + // This node is down, it's ok to invoke done right now. Don't invoke this + // in place to avoid the dead writeLock issue when done.Run() is going to acquire + // a writeLock which is already held by the caller + if (shutdownHook != null) { + shutdownHook.run(Status.OK()); + } + } + }); + } } @@ -2850,6 +2861,8 @@ public synchronized void join() throws InterruptedException { } this.shutdownLatch.await(); this.applyDisruptor.shutdown(); + this.applyQueue = null; + this.applyDisruptor = null; this.shutdownLatch = null; } if (this.fsmCaller != null) {