Allow blocking calls inside HashedWheelTimer start() and stop() (#10810)

Motivation:

When a HashedWheelTimer instance is started or stopped, its working
thread is started or stopped. These operations block the calling
thread:
- start() calls java.util.concurrent.CountDownLatch.await() to wait
for the worker thread to finish initializing;
- stop() calls java.lang.Thread.join(long) to wait for the worker
thread to exit.
BlockHound detects these calls and as a consequence, prevents
HashedWheelTimer from working properly, if it is started or stopped
in a thread that is not allowed to block.

Modifications:

Added two more BlockHound exceptions to
io.netty.util.internal.Hidden.NettyBlockHoundIntegration: one
for HashedWheelTimer.start() and one for HashedWheelTimer.stop().

Result:

HashedWheelTimer can now be started and stopped properly when
BlockHound is activated.
This commit is contained in:
Alexandre Dutra 2020-11-23 08:41:07 +01:00 committed by GitHub
parent c1ba23933c
commit 2ff8973f69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 0 deletions

View File

@ -55,6 +55,16 @@ class Hidden {
"handleLoopException"
);
builder.allowBlockingCallsInside(
"io.netty.util.HashedWheelTimer",
"start"
);
builder.allowBlockingCallsInside(
"io.netty.util.HashedWheelTimer",
"stop"
);
builder.allowBlockingCallsInside(
"io.netty.util.HashedWheelTimer$Worker",
"waitForNextTick"

View File

@ -34,6 +34,7 @@ import io.netty.handler.ssl.SslHandshakeCompletionEvent;
import io.netty.handler.ssl.SslProvider;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.util.HashedWheelTimer;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.EventExecutor;
@ -57,6 +58,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
@ -127,6 +129,15 @@ public class NettyBlockHoundIntegrationTest {
latch.await();
}
@Test(timeout = 5000L)
public void testHashedWheelTimerStartStop() throws Exception {
HashedWheelTimer timer = new HashedWheelTimer();
Future<?> futureStart = GlobalEventExecutor.INSTANCE.submit(timer::start);
futureStart.get(5, TimeUnit.SECONDS);
Future<?> futureStop = GlobalEventExecutor.INSTANCE.submit(timer::stop);
futureStop.get(5, TimeUnit.SECONDS);
}
// Tests copied from io.netty.handler.ssl.SslHandlerTest
@Test
public void testHandshakeWithExecutorThatExecuteDirectory() throws Exception {