Просмотр исходного кода

Fix occasional timeout exception in the feedback code.

Do not call `PsiphonTunnelFeedback.shutdownAndAwaitTermination()` from `finalize()`.
If the system decides to sleep in the middle of GC run a timeout may occur when the
system wakes up. Instead initialize the executor queues at the very beginning of
`startSendFeedback()` and shut them down at the very end of `stopSendFeedback()`.
Eugene Fryntov 3 лет назад
Родитель
Сommit
a158d7ed31
1 измененных файлов с 12 добавлено и 16 удалено
  1. 12 16
      MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java

+ 12 - 16
MobileLibrary/Android/PsiphonTunnel/PsiphonTunnel.java

@@ -340,21 +340,8 @@ public class PsiphonTunnel {
     // instances in parallel, or concurrently, will result in undefined behavior.
     public static class PsiphonTunnelFeedback {
 
-        final private ExecutorService workQueue;
-        final private ExecutorService callbackQueue;
-
-        public PsiphonTunnelFeedback() {
-            workQueue = Executors.newSingleThreadExecutor();
-            callbackQueue = Executors.newSingleThreadExecutor();
-        }
-
-        @Override
-        protected void finalize() throws Throwable {
-            // Ensure the queues are cleaned up.
-            shutdownAndAwaitTermination(callbackQueue);
-            shutdownAndAwaitTermination(workQueue);
-            super.finalize();
-        }
+        private ExecutorService workQueue;
+        private ExecutorService callbackQueue;
 
         void shutdownAndAwaitTermination(ExecutorService pool) {
             try {
@@ -398,6 +385,9 @@ public class PsiphonTunnel {
         public void startSendFeedback(Context context, HostFeedbackHandler feedbackHandler, HostLogger logger,
                                       String feedbackConfigJson, String diagnosticsJson, String uploadPath,
                                       String clientPlatformPrefix, String clientPlatformSuffix) {
+            // initialize executor queues
+            workQueue = Executors.newSingleThreadExecutor();
+            callbackQueue = Executors.newSingleThreadExecutor();
 
             workQueue.submit(new Runnable() {
                 @Override
@@ -526,12 +516,18 @@ public class PsiphonTunnel {
         // call is asynchronous and returns a future which is fulfilled when the underlying stop
         // operation completes.
         public Future<Void> stopSendFeedback() {
-            return workQueue.submit(new Runnable() {
+            Future<Void> result = workQueue.submit(new Runnable() {
                 @Override
                 public void run() {
                     Psi.stopSendFeedback();
                 }
             }, null);
+
+            // Also shutdown executor queues
+            shutdownAndAwaitTermination(workQueue);
+            shutdownAndAwaitTermination(callbackQueue);
+
+            return result;
         }
     }