Skip to content

Commit 3bd078d

Browse files
authored
Properly synchronize access to httpClientBuilder_ (#1015)
* Properly synchronize access to httpClientBuilder_
1 parent da587ec commit 3bd078d

File tree

1 file changed

+27
-20
lines changed

1 file changed

+27
-20
lines changed

src/main/java/org/htmlunit/HttpWebConnection.java

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ public class HttpWebConnection implements WebConnection {
137137
private static final String HACKED_COOKIE_POLICY = "mine";
138138

139139
// have one per thread because this is (re)configured for every call (see configureHttpProcessorBuilder)
140-
// do not use a ThreadLocal because this in only accessed form this class
140+
// do not use a ThreadLocal because this in only accessed form this class, but we still need it synchronized
141141
private final Map<Thread, HttpClientBuilder> httpClientBuilder_ = new WeakHashMap<>();
142142
private final WebClient webClient_;
143143

@@ -211,7 +211,9 @@ public WebResponse getResponse(final WebRequest webRequest) throws IOException {
211211
// Calling code may catch the StackOverflowError, but due to the leak, the httpClient_ may
212212
// come out of connections and throw a ConnectionPoolTimeoutException.
213213
// => best solution, discard the HttpClient instance.
214-
httpClientBuilder_.remove(Thread.currentThread());
214+
synchronized (httpClientBuilder_) {
215+
httpClientBuilder_.remove(Thread.currentThread());
216+
}
215217
throw e;
216218
}
217219
}
@@ -531,24 +533,27 @@ private static HttpRequestBase buildHttpMethod(final HttpMethod submitMethod, fi
531533
* @return the initialized HTTP client
532534
*/
533535
protected HttpClientBuilder getHttpClientBuilder() {
534-
final Thread currentThread = Thread.currentThread();
535-
HttpClientBuilder builder = httpClientBuilder_.get(currentThread);
536-
if (builder == null) {
537-
builder = createHttpClientBuilder();
538-
539-
// this factory is required later
540-
// to be sure this is done, we do it outside the createHttpClient() call
541-
final RegistryBuilder<CookieSpecProvider> registeryBuilder
542-
= RegistryBuilder.<CookieSpecProvider>create()
543-
.register(HACKED_COOKIE_POLICY, htmlUnitCookieSpecProvider_);
544-
builder.setDefaultCookieSpecRegistry(registeryBuilder.build());
545-
546-
builder.setDefaultCookieStore(new HtmlUnitCookieStore(webClient_.getCookieManager()));
547-
builder.setUserAgent(webClient_.getBrowserVersion().getUserAgent());
548-
httpClientBuilder_.put(currentThread, builder);
536+
synchronized (httpClientBuilder_)
537+
{
538+
final Thread currentThread = Thread.currentThread();
539+
HttpClientBuilder builder = httpClientBuilder_.get(currentThread);
540+
if (builder == null) {
541+
builder = createHttpClientBuilder();
542+
543+
// this factory is required later
544+
// to be sure this is done, we do it outside the createHttpClient() call
545+
final RegistryBuilder<CookieSpecProvider> registeryBuilder
546+
= RegistryBuilder.<CookieSpecProvider>create()
547+
.register(HACKED_COOKIE_POLICY, htmlUnitCookieSpecProvider_);
548+
builder.setDefaultCookieSpecRegistry(registeryBuilder.build());
549+
550+
builder.setDefaultCookieStore(new HtmlUnitCookieStore(webClient_.getCookieManager()));
551+
builder.setUserAgent(webClient_.getBrowserVersion().getUserAgent());
552+
httpClientBuilder_.put(currentThread, builder);
553+
}
554+
555+
return builder;
549556
}
550-
551-
return builder;
552557
}
553558

554559
/**
@@ -1288,7 +1293,9 @@ public synchronized String toString() {
12881293
*/
12891294
@Override
12901295
public void close() {
1291-
httpClientBuilder_.clear();
1296+
synchronized (httpClientBuilder_) {
1297+
httpClientBuilder_.clear();
1298+
}
12921299
sharedAuthCache_.clear();
12931300
httpClientContextByThread_.clear();
12941301

0 commit comments

Comments
 (0)