From d9fc8d18d1ad3ba28819a8b47912fdb0d28b1dfe Mon Sep 17 00:00:00 2001 From: akwizgran <akwizgran@users.sourceforge.net> Date: Thu, 8 Dec 2011 13:55:19 +0000 Subject: [PATCH] Better handling of InterruptedExceptions. --- .../net/sf/briar/db/DatabaseCleanerImpl.java | 3 ++ .../net/sf/briar/db/DatabaseExecutorImpl.java | 7 +++++ components/net/sf/briar/db/JdbcDatabase.java | 6 +++- .../lifecycle/WindowsShutdownManagerImpl.java | 6 +++- .../net/sf/briar/plugins/PollerImpl.java | 3 ++ .../plugins/bluetooth/BluetoothPlugin.java | 31 ++++++++++++++++--- .../plugins/bluetooth/ConnectionCallback.java | 9 ++---- .../plugins/bluetooth/ContactListener.java | 8 ++--- .../plugins/bluetooth/InvitationListener.java | 8 ++--- .../sf/briar/plugins/file/FileListener.java | 9 ++---- .../net/sf/briar/plugins/file/FilePlugin.java | 11 +++++-- .../file/PollingRemovableDriveMonitor.java | 8 +++++ .../protocol/VerificationExecutorImpl.java | 7 +++++ .../sf/briar/transport/FrameScheduler.java | 28 ++++++++++------- .../transport/PaddedConnectionWriter.java | 9 +++++- .../transport/stream/StreamConnection.java | 14 ++++----- 16 files changed, 115 insertions(+), 52 deletions(-) diff --git a/components/net/sf/briar/db/DatabaseCleanerImpl.java b/components/net/sf/briar/db/DatabaseCleanerImpl.java index e1242850f5..a5c6fb194e 100644 --- a/components/net/sf/briar/db/DatabaseCleanerImpl.java +++ b/components/net/sf/briar/db/DatabaseCleanerImpl.java @@ -37,7 +37,10 @@ class DatabaseCleanerImpl implements DatabaseCleaner, Runnable { try { wait(msBetweenSweeps); } catch(InterruptedException e) { + if(LOG.isLoggable(Level.INFO)) + LOG.info("Interrupted while waiting to clean"); Thread.currentThread().interrupt(); + return; } } } catch(DbException e) { diff --git a/components/net/sf/briar/db/DatabaseExecutorImpl.java b/components/net/sf/briar/db/DatabaseExecutorImpl.java index 8692b3e927..f6e0d1cf0f 100644 --- a/components/net/sf/briar/db/DatabaseExecutorImpl.java +++ b/components/net/sf/briar/db/DatabaseExecutorImpl.java @@ -5,6 +5,8 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; /** * An executor that limits the number of concurrent database tasks and the @@ -26,6 +28,9 @@ class DatabaseExecutorImpl implements Executor { /** The maximum number of concurrent tasks. */ private static final int MAX_THREADS = 10; + private static final Logger LOG = + Logger.getLogger(DatabaseExecutorImpl.class.getName()); + private final BlockingQueue<Runnable> queue; DatabaseExecutorImpl() { @@ -43,6 +48,8 @@ class DatabaseExecutorImpl implements Executor { // Block until there's space in the queue queue.put(r); } catch(InterruptedException e) { + if(LOG.isLoggable(Level.INFO)) + LOG.info("Interrupted while queueing task"); Thread.currentThread().interrupt(); } } diff --git a/components/net/sf/briar/db/JdbcDatabase.java b/components/net/sf/briar/db/JdbcDatabase.java index 441dd7b3c9..6cd1e1155f 100644 --- a/components/net/sf/briar/db/JdbcDatabase.java +++ b/components/net/sf/briar/db/JdbcDatabase.java @@ -446,6 +446,7 @@ abstract class JdbcDatabase implements Database<Connection> { } protected void closeAllConnections() throws SQLException { + boolean interrupted = false; synchronized(connections) { closed = true; for(Connection c : connections) c.close(); @@ -455,13 +456,16 @@ abstract class JdbcDatabase implements Database<Connection> { try { connections.wait(); } catch(InterruptedException e) { - Thread.currentThread().interrupt(); + if(LOG.isLoggable(Level.INFO)) + LOG.info("Interrupted while closing connections"); + interrupted = true; } for(Connection c : connections) c.close(); openConnections -= connections.size(); connections.clear(); } } + if(interrupted) Thread.currentThread().interrupt(); } public void addBatchToAck(Connection txn, ContactId c, BatchId b) diff --git a/components/net/sf/briar/lifecycle/WindowsShutdownManagerImpl.java b/components/net/sf/briar/lifecycle/WindowsShutdownManagerImpl.java index a84b52440b..bd1316e602 100644 --- a/components/net/sf/briar/lifecycle/WindowsShutdownManagerImpl.java +++ b/components/net/sf/briar/lifecycle/WindowsShutdownManagerImpl.java @@ -70,6 +70,7 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl { // Package access for testing synchronized void runShutdownHooks() { + boolean interrupted = false; // Start each hook in its own thread for(Thread hook : hooks.values()) hook.start(); // Wait for all the hooks to finish @@ -77,9 +78,12 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl { try { hook.join(); } catch(InterruptedException e) { - Thread.currentThread().interrupt(); + if(LOG.isLoggable(Level.INFO)) + LOG.info("Interrupted while running shutdown hooks"); + interrupted = true; } } + if(interrupted) Thread.currentThread().interrupt(); } private class EventLoop extends Thread { diff --git a/components/net/sf/briar/plugins/PollerImpl.java b/components/net/sf/briar/plugins/PollerImpl.java index 593b625a2b..75de03ae6d 100644 --- a/components/net/sf/briar/plugins/PollerImpl.java +++ b/components/net/sf/briar/plugins/PollerImpl.java @@ -52,7 +52,10 @@ class PollerImpl implements Poller, Runnable { try { wait(p.time - now); } catch(InterruptedException e) { + if(LOG.isLoggable(Level.INFO)) + LOG.info("Interrupted while waiting to poll"); Thread.currentThread().interrupt(); + return; } } } diff --git a/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java b/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java index a06c13a262..b6c53a4b22 100644 --- a/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java +++ b/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java @@ -246,11 +246,18 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin { synchronized(discoveryLock) { try { discoveryAgent.startInquiry(DiscoveryAgent.GIAC, listener); - return listener.waitForUrls(); } catch(BluetoothStateException e) { if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage()); return Collections.emptyMap(); } + try { + return listener.waitForUrls(); + } catch(InterruptedException e) { + if(LOG.isLoggable(Level.INFO)) + LOG.info("Interrupted while waiting for URLs"); + Thread.currentThread().interrupt(); + return Collections.emptyMap(); + } } } @@ -294,8 +301,15 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin { ConnectionCallback c = new ConnectionCallback(uuid, timeout); startOutgoingInvitationThread(c); startIncomingInvitationThread(c); - StreamConnection s = c.waitForConnection(); - return s == null ? null : new BluetoothTransportConnection(s); + try { + StreamConnection s = c.waitForConnection(); + return s == null ? null : new BluetoothTransportConnection(s); + } catch(InterruptedException e) { + if(LOG.isLoggable(Level.INFO)) + LOG.info("Interrupted while waiting for connection"); + Thread.currentThread().interrupt(); + return null; + } } private String convertInvitationCodeToUuid(int code) { @@ -333,6 +347,11 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin { if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage()); return; + } catch(InterruptedException e) { + if(LOG.isLoggable(Level.INFO)) + LOG.info("Interrupted while waiting for URL"); + Thread.currentThread().interrupt(); + return; } } synchronized(this) { @@ -376,9 +395,13 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin { // Close the socket when the invitation times out try { Thread.sleep(c.getTimeout()); - scn.close(); } catch(InterruptedException e) { + if(LOG.isLoggable(Level.INFO)) + LOG.info("Interrupted while waiting for invitation timeout"); Thread.currentThread().interrupt(); + } + try { + scn.close(); } catch(IOException e) { if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage()); } diff --git a/components/net/sf/briar/plugins/bluetooth/ConnectionCallback.java b/components/net/sf/briar/plugins/bluetooth/ConnectionCallback.java index 3e75bd2b37..7700263f3a 100644 --- a/components/net/sf/briar/plugins/bluetooth/ConnectionCallback.java +++ b/components/net/sf/briar/plugins/bluetooth/ConnectionCallback.java @@ -31,14 +31,11 @@ class ConnectionCallback { return timeout; } - synchronized StreamConnection waitForConnection() { + synchronized StreamConnection waitForConnection() + throws InterruptedException { long now = System.currentTimeMillis(); while(connection == null && now < end) { - try { - wait(end - now); - } catch(InterruptedException e) { - Thread.currentThread().interrupt(); - } + wait(end - now); now = System.currentTimeMillis(); } return connection; diff --git a/components/net/sf/briar/plugins/bluetooth/ContactListener.java b/components/net/sf/briar/plugins/bluetooth/ContactListener.java index c5e765cb11..5f52a43539 100644 --- a/components/net/sf/briar/plugins/bluetooth/ContactListener.java +++ b/components/net/sf/briar/plugins/bluetooth/ContactListener.java @@ -34,12 +34,8 @@ class ContactListener extends AbstractListener { urls = Collections.synchronizedMap(new HashMap<ContactId, String>()); } - Map<ContactId, String> waitForUrls() { - try { - finished.await(); - } catch(InterruptedException e) { - Thread.currentThread().interrupt(); - } + Map<ContactId, String> waitForUrls() throws InterruptedException { + finished.await(); return urls; } diff --git a/components/net/sf/briar/plugins/bluetooth/InvitationListener.java b/components/net/sf/briar/plugins/bluetooth/InvitationListener.java index 993086a798..e7f35bf162 100644 --- a/components/net/sf/briar/plugins/bluetooth/InvitationListener.java +++ b/components/net/sf/briar/plugins/bluetooth/InvitationListener.java @@ -26,12 +26,8 @@ class InvitationListener extends AbstractListener { this.uuid = uuid; } - String waitForUrl() { - try { - finished.await(); - } catch(InterruptedException e) { - Thread.currentThread().interrupt(); - } + String waitForUrl() throws InterruptedException { + finished.await(); return url; } diff --git a/components/net/sf/briar/plugins/file/FileListener.java b/components/net/sf/briar/plugins/file/FileListener.java index 367764ad2d..53142c138b 100644 --- a/components/net/sf/briar/plugins/file/FileListener.java +++ b/components/net/sf/briar/plugins/file/FileListener.java @@ -17,13 +17,8 @@ class FileListener { end = System.currentTimeMillis() + timeout; } - File waitForFile() { - long now = System.currentTimeMillis(); - try { - finished.await(end - now, TimeUnit.MILLISECONDS); - } catch(InterruptedException e) { - Thread.currentThread().interrupt(); - } + File waitForFile() throws InterruptedException { + finished.await(end - System.currentTimeMillis(), TimeUnit.MILLISECONDS); return file; } diff --git a/components/net/sf/briar/plugins/file/FilePlugin.java b/components/net/sf/briar/plugins/file/FilePlugin.java index 3e9f080300..de1b0466be 100644 --- a/components/net/sf/briar/plugins/file/FilePlugin.java +++ b/components/net/sf/briar/plugins/file/FilePlugin.java @@ -116,8 +116,15 @@ abstract class FilePlugin extends AbstractPlugin implements BatchPlugin { if(files.isEmpty()) { // Wait for a matching file to arrive listener = new FileListener(filename, timeout); - File f = listener.waitForFile(); - if(f != null) files.add(f); + File f; + try { + f = listener.waitForFile(); + if(f != null) files.add(f); + } catch(InterruptedException e) { + if(LOG.isLoggable(Level.INFO)) + LOG.info("Interrupted while waiting for file"); + Thread.currentThread().interrupt(); + } listener = null; } } diff --git a/components/net/sf/briar/plugins/file/PollingRemovableDriveMonitor.java b/components/net/sf/briar/plugins/file/PollingRemovableDriveMonitor.java index 72f9e9eaea..05fd5a057f 100644 --- a/components/net/sf/briar/plugins/file/PollingRemovableDriveMonitor.java +++ b/components/net/sf/briar/plugins/file/PollingRemovableDriveMonitor.java @@ -3,9 +3,14 @@ package net.sf.briar.plugins.file; import java.io.File; import java.io.IOException; import java.util.Collection; +import java.util.logging.Level; +import java.util.logging.Logger; class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable { + private static final Logger LOG = + Logger.getLogger(PollingRemovableDriveMonitor.class.getName()); + private final RemovableDriveFinder finder; private final long pollingInterval; private final Object pollingLock = new Object(); @@ -48,7 +53,10 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable { try { pollingLock.wait(pollingInterval); } catch(InterruptedException e) { + if(LOG.isLoggable(Level.INFO)) + LOG.info("Interrupted while waiting to poll"); Thread.currentThread().interrupt(); + return; } } if(!running) return; diff --git a/components/net/sf/briar/protocol/VerificationExecutorImpl.java b/components/net/sf/briar/protocol/VerificationExecutorImpl.java index 203ae33ffd..0c8b439a82 100644 --- a/components/net/sf/briar/protocol/VerificationExecutorImpl.java +++ b/components/net/sf/briar/protocol/VerificationExecutorImpl.java @@ -5,6 +5,8 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; /** * An executor that limits the number of concurrent message verification tasks @@ -23,6 +25,9 @@ class VerificationExecutorImpl implements Executor { /** The number of idle threads to keep in the pool. */ private static final int MIN_THREADS = 1; + private static final Logger LOG = + Logger.getLogger(VerificationExecutorImpl.class.getName()); + private final BlockingQueue<Runnable> queue; VerificationExecutorImpl() { @@ -41,6 +46,8 @@ class VerificationExecutorImpl implements Executor { // Block until there's space in the queue queue.put(r); } catch(InterruptedException e) { + if(LOG.isLoggable(Level.INFO)) + LOG.info("Interrupted while queueing task"); Thread.currentThread().interrupt(); } } diff --git a/components/net/sf/briar/transport/FrameScheduler.java b/components/net/sf/briar/transport/FrameScheduler.java index 2b0d0a9b6e..1a3f02d065 100644 --- a/components/net/sf/briar/transport/FrameScheduler.java +++ b/components/net/sf/briar/transport/FrameScheduler.java @@ -2,6 +2,9 @@ package net.sf.briar.transport; import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; +import java.util.logging.Level; +import java.util.logging.Logger; + /** * A thread that calls the writeFullFrame() method of a PaddedConnectionWriter * at regular intervals. The interval between calls is determined by a target @@ -10,6 +13,9 @@ import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; */ class FrameScheduler extends Thread { + private static final Logger LOG = + Logger.getLogger(FrameScheduler.class.getName()); + private final PaddedConnectionWriter writer; private final int millisPerFrame; @@ -21,18 +27,18 @@ class FrameScheduler extends Thread { @Override public void run() { long lastCall = System.currentTimeMillis(); - while(true) { - long now = System.currentTimeMillis(); - long nextCall = lastCall + millisPerFrame; - if(nextCall > now) { - try { - Thread.sleep(nextCall - now); - } catch(InterruptedException e) { - Thread.currentThread().interrupt(); - } + try { + while(true) { + long now = System.currentTimeMillis(); + long nextCall = lastCall + millisPerFrame; + if(nextCall > now) Thread.sleep(nextCall - now); + lastCall = System.currentTimeMillis(); + if(!writer.writeFullFrame()) return; } - lastCall = System.currentTimeMillis(); - if(!writer.writeFullFrame()) return; + } catch(InterruptedException e) { + if(LOG.isLoggable(Level.INFO)) + LOG.info("Interrupted while waiting to write frame"); + Thread.currentThread().interrupt(); } } } \ No newline at end of file diff --git a/components/net/sf/briar/transport/PaddedConnectionWriter.java b/components/net/sf/briar/transport/PaddedConnectionWriter.java index 6bc7c2762b..4bdbb5572e 100644 --- a/components/net/sf/briar/transport/PaddedConnectionWriter.java +++ b/components/net/sf/briar/transport/PaddedConnectionWriter.java @@ -3,10 +3,12 @@ package net.sf.briar.transport; import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.crypto.Mac; -import net.sf.briar.api.crypto.ErasableKey; +import net.sf.briar.api.crypto.ErasableKey; import net.sf.briar.util.ByteUtils; /** @@ -17,6 +19,9 @@ import net.sf.briar.util.ByteUtils; */ class PaddedConnectionWriter extends ConnectionWriterImpl { + private static final Logger LOG = + Logger.getLogger(PaddedConnectionWriter.class.getName()); + private final byte[] padding; private boolean closed = false; @@ -108,6 +113,8 @@ class PaddedConnectionWriter extends ConnectionWriterImpl { try { wait(); } catch(InterruptedException e) { + if(LOG.isLoggable(Level.INFO)) + LOG.info("Interrupted while waiting for space"); Thread.currentThread().interrupt(); } if(exception != null) throw exception; diff --git a/components/net/sf/briar/transport/stream/StreamConnection.java b/components/net/sf/briar/transport/stream/StreamConnection.java index 8540e0b40e..a3af59c873 100644 --- a/components/net/sf/briar/transport/stream/StreamConnection.java +++ b/components/net/sf/briar/transport/stream/StreamConnection.java @@ -199,18 +199,18 @@ abstract class StreamConnection implements DatabaseListener { dbExecutor.execute(new GenerateOffer()); // Main loop while(true) { - try { - Runnable task = writerTasks.take(); - if(task == CLOSE) break; - task.run(); - } catch(InterruptedException e) { - Thread.currentThread().interrupt(); - } + Runnable task = writerTasks.take(); + if(task == CLOSE) break; + task.run(); } if(!disposed.getAndSet(true)) transport.dispose(true); } catch(DbException e) { if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage()); if(!disposed.getAndSet(true)) transport.dispose(false); + } catch(InterruptedException e) { + if(LOG.isLoggable(Level.INFO)) + LOG.info("Interrupted while waiting for task"); + if(!disposed.getAndSet(true)) transport.dispose(false); } catch(IOException e) { if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage()); if(!disposed.getAndSet(true)) transport.dispose(false); -- GitLab