2222import com .launchdarkly .sdk .json .SerializationException ;
2323
2424import java .net .URI ;
25- import java .util .concurrent .ExecutorService ;
2625import java .util .concurrent .TimeUnit ;
2726
2827import okhttp3 .OkHttpClient ;
@@ -63,7 +62,6 @@ final class StreamingDataSource implements DataSource {
6362 private final boolean streamEvenInBackground ;
6463 private volatile boolean running = false ;
6564 private boolean connection401Error = false ;
66- private final ExecutorService executor ;
6765 private final DiagnosticStore diagnosticStore ;
6866 private long eventSourceStarted ;
6967 private final LDLogger logger ;
@@ -87,7 +85,6 @@ final class StreamingDataSource implements DataSource {
8785 this .streamEvenInBackground = streamEvenInBackground ;
8886 this .diagnosticStore = ClientContextImpl .get (clientContext ).getDiagnosticStore ();
8987 this .logger = clientContext .getBaseLogger ();
90- executor = new BackgroundThreadExecutor ().newFixedThreadPool (2 );
9188 }
9289
9390 public void start (@ NonNull Callback <Boolean > resultCallback ) {
@@ -241,12 +238,22 @@ public void stop(final @NonNull Callback<Void> onCompleteListener) {
241238 logger .debug ("Stopping." );
242239 // We do this in a separate thread because closing the stream involves a network
243240 // operation and we don't want to do a network operation on the main thread.
244- executor .execute (() -> {
241+ // This code originally created a one-shot thread for shutting down the event source, but at some point
242+ // an Executor was introduced. A thread leak bug was introduced with that Executor because the Executor
243+ // was not cleaned up. The thread leak bug was brought to our attention in
244+ // https://github.com/launchdarkly/android-client-sdk/issues/234 . Over time, the code evolved to no longer
245+ // need the Executor to be long lived. Reverting to the one-shot thread approach is sufficient to address
246+ // the bug. A more appropriate fix would be to refactor/unify the various task executors in the code base
247+ // and pass one of those executors in to be used for this purpose. That refactoring is not without risk and
248+ // will be reserved for a future major version.
249+ new Thread (() -> {
250+ // Moves the current Thread into the background.
251+ android .os .Process .setThreadPriority (android .os .Process .THREAD_PRIORITY_BACKGROUND );
245252 stopSync ();
246253 if (onCompleteListener != null ) {
247254 onCompleteListener .onSuccess (null );
248255 }
249- });
256+ }). start () ;
250257 }
251258
252259 @ Override
0 commit comments