View Javadoc
1   /*
2    * Copyright 2019 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  
17  package io.netty.util.internal;
18  
19  import io.netty.util.concurrent.FastThreadLocalThread;
20  import reactor.blockhound.BlockHound;
21  import reactor.blockhound.integration.BlockHoundIntegration;
22  
23  import java.util.function.Function;
24  import java.util.function.Predicate;
25  
26  /**
27   * Contains classes that must have public visibility but are not public API.
28   */
29  class Hidden {
30  
31      /**
32       * This class integrates Netty with BlockHound.
33       * <p>
34       * It is public but only because of the ServiceLoader's limitations
35       * and SHOULD NOT be considered a public API.
36       */
37      @UnstableApi
38      @SuppressJava6Requirement(reason = "BlockHound is Java 8+, but this class is only loaded by it's SPI")
39      public static final class NettyBlockHoundIntegration implements BlockHoundIntegration {
40  
41          @Override
42          public void applyTo(BlockHound.Builder builder) {
43              builder.allowBlockingCallsInside(
44                      "io.netty.channel.nio.NioEventLoop",
45                      "handleLoopException"
46              );
47  
48              builder.allowBlockingCallsInside(
49                      "io.netty.channel.kqueue.KQueueEventLoop",
50                      "handleLoopException"
51              );
52  
53              builder.allowBlockingCallsInside(
54                      "io.netty.channel.epoll.EpollEventLoop",
55                      "handleLoopException"
56              );
57  
58              builder.allowBlockingCallsInside(
59                      "io.netty.util.HashedWheelTimer",
60                      "start"
61              );
62  
63              builder.allowBlockingCallsInside(
64                      "io.netty.util.HashedWheelTimer",
65                      "stop"
66              );
67  
68              builder.allowBlockingCallsInside(
69                      "io.netty.util.HashedWheelTimer$Worker",
70                      "waitForNextTick"
71              );
72  
73              builder.allowBlockingCallsInside(
74                      "io.netty.util.concurrent.SingleThreadEventExecutor",
75                      "confirmShutdown"
76              );
77  
78              builder.allowBlockingCallsInside(
79                      "io.netty.buffer.PoolArena",
80                      "lock"
81              );
82  
83              builder.allowBlockingCallsInside(
84                      "io.netty.buffer.PoolSubpage",
85                      "lock"
86              );
87  
88              builder.allowBlockingCallsInside(
89                      "io.netty.buffer.PoolChunk",
90                      "allocateRun"
91              );
92  
93              builder.allowBlockingCallsInside(
94                      "io.netty.buffer.PoolChunk",
95                      "free"
96              );
97  
98              builder.allowBlockingCallsInside(
99                      "io.netty.buffer.AdaptivePoolingAllocator$1",
100                     "initialValue"
101             );
102 
103             builder.allowBlockingCallsInside(
104                     "io.netty.buffer.AdaptivePoolingAllocator$1",
105                     "onRemoval"
106             );
107 
108             builder.allowBlockingCallsInside(
109                     "io.netty.buffer.AdaptivePoolingAllocator$Magazine",
110                     "free"
111             );
112 
113             builder.allowBlockingCallsInside(
114                     "io.netty.handler.ssl.SslHandler",
115                     "handshake"
116             );
117 
118             builder.allowBlockingCallsInside(
119                     "io.netty.handler.ssl.SslHandler",
120                     "runAllDelegatedTasks"
121             );
122             builder.allowBlockingCallsInside(
123                     "io.netty.handler.ssl.SslHandler",
124                     "runDelegatedTasks"
125             );
126             builder.allowBlockingCallsInside(
127                     "io.netty.util.concurrent.GlobalEventExecutor",
128                     "takeTask");
129 
130             builder.allowBlockingCallsInside(
131                     "io.netty.util.concurrent.GlobalEventExecutor",
132                     "addTask");
133 
134             builder.allowBlockingCallsInside(
135                     "io.netty.util.concurrent.SingleThreadEventExecutor",
136                     "takeTask");
137 
138             builder.allowBlockingCallsInside(
139                     "io.netty.util.concurrent.SingleThreadEventExecutor",
140                     "addTask");
141 
142             builder.allowBlockingCallsInside(
143                     "io.netty.handler.ssl.ReferenceCountedOpenSslClientContext$ExtendedTrustManagerVerifyCallback",
144                     "verify");
145 
146             builder.allowBlockingCallsInside(
147                     "io.netty.handler.ssl.JdkSslContext$Defaults",
148                     "init");
149 
150             // Let's whitelist SSLEngineImpl.unwrap(...) for now as it may fail otherwise for TLS 1.3.
151             // See https://mail.openjdk.java.net/pipermail/security-dev/2020-August/022271.html
152             builder.allowBlockingCallsInside(
153                     "sun.security.ssl.SSLEngineImpl",
154                     "unwrap");
155 
156             builder.allowBlockingCallsInside(
157                     "sun.security.ssl.SSLEngineImpl",
158                     "wrap");
159 
160             builder.allowBlockingCallsInside(
161                     "io.netty.resolver.dns.UnixResolverDnsServerAddressStreamProvider",
162                     "parse");
163 
164             builder.allowBlockingCallsInside(
165                     "io.netty.resolver.dns.UnixResolverDnsServerAddressStreamProvider",
166                     "parseEtcResolverSearchDomains");
167 
168             builder.allowBlockingCallsInside(
169                     "io.netty.resolver.dns.UnixResolverDnsServerAddressStreamProvider",
170                     "parseEtcResolverOptions");
171 
172             builder.allowBlockingCallsInside(
173                     "io.netty.resolver.dns.DnsQueryIdSpace",
174                     "nextId");
175 
176             builder.allowBlockingCallsInside(
177                     "io.netty.resolver.dns.DnsQueryIdSpace$DnsQueryIdRange",
178                     "pushId");
179 
180             builder.allowBlockingCallsInside(
181                     "io.netty.resolver.HostsFileEntriesProvider$ParserImpl",
182                     "parse");
183 
184             builder.allowBlockingCallsInside(
185                     "io.netty.util.NetUtil$SoMaxConnAction",
186                     "run");
187 
188             builder.allowBlockingCallsInside("io.netty.util.internal.ReferenceCountUpdater",
189                     "retryRelease0");
190 
191             builder.allowBlockingCallsInside("io.netty.util.internal.PlatformDependent", "createTempFile");
192             builder.nonBlockingThreadPredicate(new Function<Predicate<Thread>, Predicate<Thread>>() {
193                 @Override
194                 public Predicate<Thread> apply(final Predicate<Thread> p) {
195                     return new Predicate<Thread>() {
196                         @Override
197                         @SuppressJava6Requirement(reason = "Predicate#test")
198                         public boolean test(Thread thread) {
199                             return p.test(thread) ||
200                                     thread instanceof FastThreadLocalThread &&
201                                             !((FastThreadLocalThread) thread).permitBlockingCalls();
202                         }
203                     };
204                 }
205             });
206         }
207 
208         @Override
209         public int compareTo(BlockHoundIntegration o) {
210             return 0;
211         }
212     }
213 }