Skip to content

Commit e79ebda

Browse files
authored
CBL-7550 : Adding shutdown for CBL Java for non daemon thread (#436) (#445)
* CBL-7550 : Adding shutdown for CBL Java for non daemon thread * Added space between shutdown function * Not setting executor service to null * Added awaitTermination for 5 sec * Resolving Cmake and Spotbug issues * Created a utility class for ExecutorService (cherry picked from commit 2b72cfb)
1 parent fe4814c commit e79ebda

4 files changed

Lines changed: 63 additions & 0 deletions

File tree

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.couchbase.lite.internal.exec;
2+
3+
import androidx.annotation.NonNull;
4+
5+
import java.util.concurrent.ExecutorService;
6+
import java.util.concurrent.TimeUnit;
7+
8+
import com.couchbase.lite.LogDomain;
9+
import com.couchbase.lite.internal.logging.Log;
10+
11+
public final class ExecutorUtils {
12+
private ExecutorUtils() {}
13+
14+
public static void shutdownAndAwaitTermination(
15+
@NonNull ExecutorService pool,
16+
int timeoutSeconds,
17+
@NonNull LogDomain logDomain) {
18+
pool.shutdown();
19+
try {
20+
if (!pool.awaitTermination(timeoutSeconds, TimeUnit.SECONDS)) {
21+
pool.shutdownNow();
22+
Log.w(logDomain, "Executor did not terminate within timeout");
23+
}
24+
} catch (InterruptedException ie) {
25+
pool.shutdownNow();
26+
Thread.currentThread().interrupt();
27+
Log.w(logDomain, "Executor shutdown interrupted", ie);
28+
}
29+
}
30+
}

common/main/java/com/couchbase/lite/internal/sockets/OkHttpSocket.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.Map;
2828
import java.util.Objects;
2929
import java.util.StringTokenizer;
30+
import java.util.concurrent.ExecutorService;
3031
import java.util.concurrent.TimeUnit;
3132
import java.util.concurrent.atomic.AtomicReference;
3233

@@ -44,6 +45,7 @@
4445
import com.couchbase.lite.LogDomain;
4546
import com.couchbase.lite.internal.core.C4Constants;
4647
import com.couchbase.lite.internal.core.C4Replicator;
48+
import com.couchbase.lite.internal.exec.ExecutorUtils;
4749
import com.couchbase.lite.internal.logging.Log;
4850
import com.couchbase.lite.internal.utils.ClassUtils;
4951
import com.couchbase.lite.internal.utils.Fn;
@@ -72,6 +74,13 @@ private interface SocketFactory {
7274

7375
.build();
7476

77+
public static void shutdownHttpClient() {
78+
final ExecutorService dispatcher = BASE_HTTP_CLIENT.dispatcher().executorService();
79+
ExecutorUtils.shutdownAndAwaitTermination(dispatcher, 5, LogDomain.NETWORK);
80+
// Clean up connection pool
81+
BASE_HTTP_CLIENT.connectionPool().evictAll();
82+
}
83+
7584
// A singleton WebSocket
7685
@NonNull
7786
private static final WebSocket NULL_WS = new WebSocket() {

java/main/java/com/couchbase/lite/internal/CouchbaseLiteInternal.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@
3535
import com.couchbase.lite.internal.exec.ExecutionService;
3636
import com.couchbase.lite.internal.logging.Log;
3737
import com.couchbase.lite.internal.logging.LogSinksImpl;
38+
import com.couchbase.lite.internal.sockets.OkHttpSocket;
3839
import com.couchbase.lite.internal.utils.FileUtils;
3940

4041

42+
4143
/**
4244
* Among the other things that this class attempts to abstract away, is access to the file system.
4345
* On both Android, and in a Web Container, file system access is pretty problematic.
@@ -161,4 +163,13 @@ private static void setC4TmpDirPath(@NonNull File scratchDir) {
161163
}
162164
catch (LiteCoreException e) { Log.w(LogDomain.DATABASE, "Failed to set c4TmpDir", e); }
163165
}
166+
167+
public static void shutdown() {
168+
final ExecutionService executionService = EXECUTION_SERVICE.get();
169+
if (executionService instanceof JavaExecutionService) {
170+
((JavaExecutionService) executionService).shutdown();
171+
}
172+
173+
OkHttpSocket.shutdownHttpClient();
174+
}
164175
}

java/main/java/com/couchbase/lite/internal/JavaExecutionService.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import androidx.annotation.VisibleForTesting;
2020

2121
import java.util.concurrent.Executor;
22+
import java.util.concurrent.ExecutorService;
2223
import java.util.concurrent.Executors;
2324
import java.util.concurrent.Future;
2425
import java.util.concurrent.RejectedExecutionException;
@@ -29,6 +30,7 @@
2930
import com.couchbase.lite.LogDomain;
3031
import com.couchbase.lite.internal.exec.AbstractExecutionService;
3132
import com.couchbase.lite.internal.exec.CBLExecutor;
33+
import com.couchbase.lite.internal.exec.ExecutorUtils;
3234
import com.couchbase.lite.internal.logging.Log;
3335
import com.couchbase.lite.internal.utils.Preconditions;
3436

@@ -100,4 +102,15 @@ public Cancellable postDelayedOnExecutor(long delayMs, @NonNull Executor executo
100102
final Future<?> future = scheduler.schedule(delayedTask, delayMs, TimeUnit.MILLISECONDS);
101103
return new CancellableTask(future);
102104
}
105+
106+
public void shutdown() {
107+
ExecutorUtils.shutdownAndAwaitTermination(
108+
(ExecutorService) defaultExecutor, 5, LogDomain.DATABASE
109+
);
110+
111+
if (scheduler != null) {
112+
ExecutorUtils.shutdownAndAwaitTermination(scheduler, 5, LogDomain.DATABASE);
113+
}
114+
getConcurrentExecutor().stop(5, TimeUnit.SECONDS);
115+
}
103116
}

0 commit comments

Comments
 (0)