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

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