From 973a2fb3954ab40e8ed2865c014b568ee95c1e70 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Sun, 6 Dec 2015 14:41:27 +0100 Subject: [PATCH] fail with exception, if crypto worker is waiting too long (1 second) to be able to write to the output stream --- .../crypto/aes256/Aes256Cryptor.java | 15 +++++++++++++-- .../crypto/aes256/CryptoWorker.java | 18 +++++++++++------- .../crypto/aes256/CryptoWorkerExecutor.java | 3 +-- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/Aes256Cryptor.java b/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/Aes256Cryptor.java index 104dbe659..e5ddd4dc5 100644 --- a/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/Aes256Cryptor.java +++ b/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/Aes256Cryptor.java @@ -24,6 +24,7 @@ import java.security.SecureRandom; import java.util.Arrays; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import javax.crypto.AEADBadTagException; import javax.crypto.BadPaddingException; @@ -499,9 +500,14 @@ public class Aes256Cryptor implements Cryptor, AesCryptographicConfiguration { try { executor.waitUntilDone(1, TimeUnit.SECONDS); } catch (ExecutionException e) { - final Throwable cause = e.getCause(); + Throwable cause = e; + while (cause instanceof ExecutionException) { + cause = cause.getCause(); + } if (cause instanceof IOException) { throw (IOException) cause; + } else if (cause instanceof TimeoutException) { + throw new DecryptFailedException(cause); } else if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else { @@ -724,9 +730,14 @@ public class Aes256Cryptor implements Cryptor, AesCryptographicConfiguration { try { executor.waitUntilDone(1, TimeUnit.SECONDS); } catch (ExecutionException e) { - final Throwable cause = e.getCause(); + Throwable cause = e; + while (cause instanceof ExecutionException) { + cause = cause.getCause(); + } if (cause instanceof IOException) { throw (IOException) cause; + } else if (cause instanceof TimeoutException) { + throw new EncryptFailedException(cause); } else if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else { diff --git a/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/CryptoWorker.java b/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/CryptoWorker.java index a7f121669..ed56e0b79 100644 --- a/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/CryptoWorker.java +++ b/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/CryptoWorker.java @@ -4,6 +4,8 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; @@ -14,10 +16,10 @@ abstract class CryptoWorker implements Callable { static final BlocksData POISON = new BlocksData(ByteBuffer.allocate(0), -1L, 0); - final Lock lock; - final Condition blockDone; - final AtomicLong currentBlock; - final BlockingQueue queue; + private final Lock lock; + private final Condition blockDone; + private final AtomicLong currentBlock; + private final BlockingQueue queue; public CryptoWorker(Lock lock, Condition blockDone, AtomicLong currentBlock, BlockingQueue queue) { this.lock = lock; @@ -27,7 +29,7 @@ abstract class CryptoWorker implements Callable { } @Override - public final Void call() throws IOException { + public final Void call() throws IOException, TimeoutException { try { while (!Thread.currentThread().isInterrupted()) { final BlocksData blocksData = queue.take(); @@ -38,7 +40,9 @@ abstract class CryptoWorker implements Callable { lock.lock(); try { while (currentBlock.get() != blocksData.startBlockNum) { - blockDone.await(); + if (!blockDone.await(1, TimeUnit.SECONDS)) { + throw new TimeoutException("Waited too long to write block " + blocksData.startBlockNum + "; Current block " + currentBlock.get()); + } } assert currentBlock.get() == blocksData.startBlockNum; // yay, its my turn! @@ -51,7 +55,7 @@ abstract class CryptoWorker implements Callable { } } } catch (InterruptedException e) { - // will happen for executorService.shutdownNow() + // will happen for executorService.shutdownNow() or future.cancel() Thread.currentThread().interrupt(); } return null; diff --git a/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/CryptoWorkerExecutor.java b/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/CryptoWorkerExecutor.java index 57bde5bb9..e63947539 100644 --- a/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/CryptoWorkerExecutor.java +++ b/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/CryptoWorkerExecutor.java @@ -68,8 +68,7 @@ class CryptoWorkerExecutor { try { final boolean success = inputQueue.offer(data, timeout, unit); if (!success) { - LOG.error("inputQueue is full."); - inputQueue.clear(); + LOG.warn("Cancelling crypto workers due to timeout. Apparently the work queue not being drained by the workers any longer."); allWork.cancel(true); } return success;