From 338e1a991c5d15695bd654a7b8d2bd4008e868ae Mon Sep 17 00:00:00 2001 From: wyzhang Date: Thu, 19 Sep 2019 02:59:51 -0700 Subject: [PATCH] Fix a bug introduced by 79706357c73ded02615d0445db7503b646ff9547 which can cause thread to spin in an infinite loop. (#9579) Motivation: peek() is implemented in a similar way to poll() for the mpsc queue, thus it is more like a consumer call. It is possible that we could have multiple thread call peek() and possibly one thread calls poll() at at the same time. This lead to multiple consumer scenario, which violates the multiple producer single consumer condition and could lead to spin in an infinite loop in peek() Modification: Use isEmpty() instead of peek() to check if task queue is empty Result: Dont violate the mpsc semantics. --- .../io/netty/util/concurrent/NonStickyEventExecutorGroup.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/io/netty/util/concurrent/NonStickyEventExecutorGroup.java b/common/src/main/java/io/netty/util/concurrent/NonStickyEventExecutorGroup.java index bcc4b82996..a2692f6696 100644 --- a/common/src/main/java/io/netty/util/concurrent/NonStickyEventExecutorGroup.java +++ b/common/src/main/java/io/netty/util/concurrent/NonStickyEventExecutorGroup.java @@ -274,7 +274,7 @@ public final class NonStickyEventExecutorGroup implements EventExecutorGroup { // // The above cases can be distinguished by performing a // compareAndSet(NONE, RUNNING). If it returns "false", it is case 1; otherwise it is case 2. - if (tasks.peek() == null || !state.compareAndSet(NONE, RUNNING)) { + if (tasks.isEmpty() || !state.compareAndSet(NONE, RUNNING)) { return; // done } }