Skip to content

Commit ed95a50

Browse files
committed
JAVA-2052: Ensure that DefaultConnectionPool only used daemon background threads
1 parent 2b00eb4 commit ed95a50

File tree

4 files changed

+85
-22
lines changed

4 files changed

+85
-22
lines changed

driver-core/src/main/com/mongodb/connection/DefaultConnectionPool.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import com.mongodb.event.ConnectionPoolOpenedEvent;
3232
import com.mongodb.event.ConnectionPoolWaitQueueEvent;
3333
import com.mongodb.internal.connection.ConcurrentPool;
34+
import com.mongodb.internal.thread.DaemonThreadFactory;
3435
import org.bson.ByteBuf;
3536

3637
import java.util.List;
@@ -49,6 +50,7 @@
4950

5051
class DefaultConnectionPool implements ConnectionPool {
5152
private static final Logger LOGGER = Loggers.getLogger("connection");
53+
private static final DaemonThreadFactory THREAD_FACTORY = new DaemonThreadFactory();
5254

5355
private final ConcurrentPool<UsageTrackingInternalConnection> pool;
5456
private final ConnectionPoolSettings settings;
@@ -207,7 +209,7 @@ public void onResult(final Void result, final Throwable t) {
207209

208210
private synchronized ExecutorService getAsyncGetter() {
209211
if (asyncGetter == null) {
210-
asyncGetter = Executors.newSingleThreadExecutor();
212+
asyncGetter = Executors.newSingleThreadExecutor(THREAD_FACTORY);
211213
}
212214
return asyncGetter;
213215
}
@@ -310,7 +312,7 @@ private ExecutorService createTimer() {
310312
if (maintenanceTask == null) {
311313
return null;
312314
} else {
313-
ScheduledExecutorService newTimer = Executors.newSingleThreadScheduledExecutor();
315+
ScheduledExecutorService newTimer = Executors.newSingleThreadScheduledExecutor(THREAD_FACTORY);
314316
newTimer.scheduleAtFixedRate(maintenanceTask, settings.getMaintenanceInitialDelay(MILLISECONDS),
315317
settings.getMaintenanceFrequency(MILLISECONDS), MILLISECONDS);
316318
return newTimer;
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2015 MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://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,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package com.mongodb.internal.thread;
19+
20+
import java.util.concurrent.ThreadFactory;
21+
import java.util.concurrent.atomic.AtomicInteger;
22+
23+
/**
24+
* Custom thread factory for scheduled executor service that creates daemon threads. Otherwise,
25+
* applications that neglect to close the client will not exit.
26+
*
27+
* <p>This class should not be considered a part of the public API.</p>
28+
*/
29+
public class DaemonThreadFactory implements ThreadFactory {
30+
private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);
31+
private final AtomicInteger threadNumber = new AtomicInteger(1);
32+
private final String namePrefix;
33+
34+
public DaemonThreadFactory() {
35+
this("pool");
36+
}
37+
38+
public DaemonThreadFactory(final String prefix) {
39+
namePrefix = prefix + "-" + POOL_NUMBER.getAndIncrement() + "-thread-";
40+
}
41+
42+
@Override
43+
public Thread newThread(final Runnable runnable) {
44+
Thread t = new Thread(runnable, namePrefix + threadNumber.getAndIncrement());
45+
t.setDaemon(true);
46+
return t;
47+
}
48+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2015 MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://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,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package com.mongodb.internal.thread
19+
20+
import spock.lang.Specification
21+
22+
class DaemonThreadFactorySpecification extends Specification {
23+
def 'should create daemon threads'() {
24+
def factory = new DaemonThreadFactory()
25+
26+
when:
27+
def thread = factory.newThread { }
28+
29+
then:
30+
thread.isDaemon()
31+
}
32+
}

driver/src/main/com/mongodb/Mongo.java

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.mongodb.event.CommandListener;
3636
import com.mongodb.event.CommandListenerMulticaster;
3737
import com.mongodb.internal.connection.PowerOfTwoBufferPool;
38+
import com.mongodb.internal.thread.DaemonThreadFactory;
3839
import com.mongodb.management.JMXConnectionPoolListener;
3940
import com.mongodb.operation.CurrentOpOperation;
4041
import com.mongodb.operation.FsyncUnlockOperation;
@@ -56,8 +57,6 @@
5657
import java.util.concurrent.ExecutorService;
5758
import java.util.concurrent.Executors;
5859
import java.util.concurrent.ScheduledExecutorService;
59-
import java.util.concurrent.ThreadFactory;
60-
import java.util.concurrent.atomic.AtomicInteger;
6160

6261
import static com.mongodb.ReadPreference.primary;
6362
import static com.mongodb.connection.ClusterConnectionMode.MULTIPLE;
@@ -897,22 +896,4 @@ private String toKey(final MongoClientURI uri) {
897896
return uri.toString();
898897
}
899898
}
900-
901-
// Custom thread factory for scheduled executor service that creates daemon threads. Otherwise,
902-
// applications that neglect to close MongoClient will not exit.
903-
static class DaemonThreadFactory implements ThreadFactory {
904-
private static final AtomicInteger poolNumber = new AtomicInteger(1);
905-
private final AtomicInteger threadNumber = new AtomicInteger(1);
906-
private final String namePrefix;
907-
908-
DaemonThreadFactory() {
909-
namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-";
910-
}
911-
912-
public Thread newThread(final Runnable runnable) {
913-
Thread t = new Thread(runnable, namePrefix + threadNumber.getAndIncrement());
914-
t.setDaemon(true);
915-
return t;
916-
}
917-
}
918899
}

0 commit comments

Comments
 (0)