Better handling of InterruptedExceptions.

This commit is contained in:
akwizgran
2011-12-08 13:55:19 +00:00
parent c1ab21ba2f
commit d9fc8d18d1
16 changed files with 115 additions and 52 deletions

View File

@@ -37,7 +37,10 @@ class DatabaseCleanerImpl implements DatabaseCleaner, Runnable {
try { try {
wait(msBetweenSweeps); wait(msBetweenSweeps);
} catch(InterruptedException e) { } catch(InterruptedException e) {
if(LOG.isLoggable(Level.INFO))
LOG.info("Interrupted while waiting to clean");
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
return;
} }
} }
} catch(DbException e) { } catch(DbException e) {

View File

@@ -5,6 +5,8 @@ import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; 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 * 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. */ /** The maximum number of concurrent tasks. */
private static final int MAX_THREADS = 10; private static final int MAX_THREADS = 10;
private static final Logger LOG =
Logger.getLogger(DatabaseExecutorImpl.class.getName());
private final BlockingQueue<Runnable> queue; private final BlockingQueue<Runnable> queue;
DatabaseExecutorImpl() { DatabaseExecutorImpl() {
@@ -43,6 +48,8 @@ class DatabaseExecutorImpl implements Executor {
// Block until there's space in the queue // Block until there's space in the queue
queue.put(r); queue.put(r);
} catch(InterruptedException e) { } catch(InterruptedException e) {
if(LOG.isLoggable(Level.INFO))
LOG.info("Interrupted while queueing task");
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
} }

View File

@@ -446,6 +446,7 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
protected void closeAllConnections() throws SQLException { protected void closeAllConnections() throws SQLException {
boolean interrupted = false;
synchronized(connections) { synchronized(connections) {
closed = true; closed = true;
for(Connection c : connections) c.close(); for(Connection c : connections) c.close();
@@ -455,13 +456,16 @@ abstract class JdbcDatabase implements Database<Connection> {
try { try {
connections.wait(); connections.wait();
} catch(InterruptedException e) { } 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(); for(Connection c : connections) c.close();
openConnections -= connections.size(); openConnections -= connections.size();
connections.clear(); connections.clear();
} }
} }
if(interrupted) Thread.currentThread().interrupt();
} }
public void addBatchToAck(Connection txn, ContactId c, BatchId b) public void addBatchToAck(Connection txn, ContactId c, BatchId b)

View File

@@ -70,6 +70,7 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl {
// Package access for testing // Package access for testing
synchronized void runShutdownHooks() { synchronized void runShutdownHooks() {
boolean interrupted = false;
// Start each hook in its own thread // Start each hook in its own thread
for(Thread hook : hooks.values()) hook.start(); for(Thread hook : hooks.values()) hook.start();
// Wait for all the hooks to finish // Wait for all the hooks to finish
@@ -77,9 +78,12 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl {
try { try {
hook.join(); hook.join();
} catch(InterruptedException e) { } 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 { private class EventLoop extends Thread {

View File

@@ -52,7 +52,10 @@ class PollerImpl implements Poller, Runnable {
try { try {
wait(p.time - now); wait(p.time - now);
} catch(InterruptedException e) { } catch(InterruptedException e) {
if(LOG.isLoggable(Level.INFO))
LOG.info("Interrupted while waiting to poll");
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
return;
} }
} }
} }

View File

@@ -246,11 +246,18 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
synchronized(discoveryLock) { synchronized(discoveryLock) {
try { try {
discoveryAgent.startInquiry(DiscoveryAgent.GIAC, listener); discoveryAgent.startInquiry(DiscoveryAgent.GIAC, listener);
return listener.waitForUrls();
} catch(BluetoothStateException e) { } catch(BluetoothStateException e) {
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage()); if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
return Collections.emptyMap(); 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); ConnectionCallback c = new ConnectionCallback(uuid, timeout);
startOutgoingInvitationThread(c); startOutgoingInvitationThread(c);
startIncomingInvitationThread(c); startIncomingInvitationThread(c);
StreamConnection s = c.waitForConnection(); try {
return s == null ? null : new BluetoothTransportConnection(s); 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) { private String convertInvitationCodeToUuid(int code) {
@@ -333,6 +347,11 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
if(LOG.isLoggable(Level.WARNING)) if(LOG.isLoggable(Level.WARNING))
LOG.warning(e.getMessage()); LOG.warning(e.getMessage());
return; return;
} catch(InterruptedException e) {
if(LOG.isLoggable(Level.INFO))
LOG.info("Interrupted while waiting for URL");
Thread.currentThread().interrupt();
return;
} }
} }
synchronized(this) { synchronized(this) {
@@ -376,9 +395,13 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
// Close the socket when the invitation times out // Close the socket when the invitation times out
try { try {
Thread.sleep(c.getTimeout()); Thread.sleep(c.getTimeout());
scn.close();
} catch(InterruptedException e) { } catch(InterruptedException e) {
if(LOG.isLoggable(Level.INFO))
LOG.info("Interrupted while waiting for invitation timeout");
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
}
try {
scn.close();
} catch(IOException e) { } catch(IOException e) {
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage()); if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
} }

View File

@@ -31,14 +31,11 @@ class ConnectionCallback {
return timeout; return timeout;
} }
synchronized StreamConnection waitForConnection() { synchronized StreamConnection waitForConnection()
throws InterruptedException {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
while(connection == null && now < end) { while(connection == null && now < end) {
try { wait(end - now);
wait(end - now);
} catch(InterruptedException e) {
Thread.currentThread().interrupt();
}
now = System.currentTimeMillis(); now = System.currentTimeMillis();
} }
return connection; return connection;

View File

@@ -34,12 +34,8 @@ class ContactListener extends AbstractListener {
urls = Collections.synchronizedMap(new HashMap<ContactId, String>()); urls = Collections.synchronizedMap(new HashMap<ContactId, String>());
} }
Map<ContactId, String> waitForUrls() { Map<ContactId, String> waitForUrls() throws InterruptedException {
try { finished.await();
finished.await();
} catch(InterruptedException e) {
Thread.currentThread().interrupt();
}
return urls; return urls;
} }

View File

@@ -26,12 +26,8 @@ class InvitationListener extends AbstractListener {
this.uuid = uuid; this.uuid = uuid;
} }
String waitForUrl() { String waitForUrl() throws InterruptedException {
try { finished.await();
finished.await();
} catch(InterruptedException e) {
Thread.currentThread().interrupt();
}
return url; return url;
} }

View File

@@ -17,13 +17,8 @@ class FileListener {
end = System.currentTimeMillis() + timeout; end = System.currentTimeMillis() + timeout;
} }
File waitForFile() { File waitForFile() throws InterruptedException {
long now = System.currentTimeMillis(); finished.await(end - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
try {
finished.await(end - now, TimeUnit.MILLISECONDS);
} catch(InterruptedException e) {
Thread.currentThread().interrupt();
}
return file; return file;
} }

View File

@@ -116,8 +116,15 @@ abstract class FilePlugin extends AbstractPlugin implements BatchPlugin {
if(files.isEmpty()) { if(files.isEmpty()) {
// Wait for a matching file to arrive // Wait for a matching file to arrive
listener = new FileListener(filename, timeout); listener = new FileListener(filename, timeout);
File f = listener.waitForFile(); File f;
if(f != null) files.add(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; listener = null;
} }
} }

View File

@@ -3,9 +3,14 @@ package net.sf.briar.plugins.file;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable { class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
private static final Logger LOG =
Logger.getLogger(PollingRemovableDriveMonitor.class.getName());
private final RemovableDriveFinder finder; private final RemovableDriveFinder finder;
private final long pollingInterval; private final long pollingInterval;
private final Object pollingLock = new Object(); private final Object pollingLock = new Object();
@@ -48,7 +53,10 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
try { try {
pollingLock.wait(pollingInterval); pollingLock.wait(pollingInterval);
} catch(InterruptedException e) { } catch(InterruptedException e) {
if(LOG.isLoggable(Level.INFO))
LOG.info("Interrupted while waiting to poll");
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
return;
} }
} }
if(!running) return; if(!running) return;

View File

@@ -5,6 +5,8 @@ import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; 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 * 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. */ /** The number of idle threads to keep in the pool. */
private static final int MIN_THREADS = 1; private static final int MIN_THREADS = 1;
private static final Logger LOG =
Logger.getLogger(VerificationExecutorImpl.class.getName());
private final BlockingQueue<Runnable> queue; private final BlockingQueue<Runnable> queue;
VerificationExecutorImpl() { VerificationExecutorImpl() {
@@ -41,6 +46,8 @@ class VerificationExecutorImpl implements Executor {
// Block until there's space in the queue // Block until there's space in the queue
queue.put(r); queue.put(r);
} catch(InterruptedException e) { } catch(InterruptedException e) {
if(LOG.isLoggable(Level.INFO))
LOG.info("Interrupted while queueing task");
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
} }

View File

@@ -2,6 +2,9 @@ package net.sf.briar.transport;
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH; 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 * A thread that calls the writeFullFrame() method of a PaddedConnectionWriter
* at regular intervals. The interval between calls is determined by a target * 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 { class FrameScheduler extends Thread {
private static final Logger LOG =
Logger.getLogger(FrameScheduler.class.getName());
private final PaddedConnectionWriter writer; private final PaddedConnectionWriter writer;
private final int millisPerFrame; private final int millisPerFrame;
@@ -21,18 +27,18 @@ class FrameScheduler extends Thread {
@Override @Override
public void run() { public void run() {
long lastCall = System.currentTimeMillis(); long lastCall = System.currentTimeMillis();
while(true) { try {
long now = System.currentTimeMillis(); while(true) {
long nextCall = lastCall + millisPerFrame; long now = System.currentTimeMillis();
if(nextCall > now) { long nextCall = lastCall + millisPerFrame;
try { if(nextCall > now) Thread.sleep(nextCall - now);
Thread.sleep(nextCall - now); lastCall = System.currentTimeMillis();
} catch(InterruptedException e) { if(!writer.writeFullFrame()) return;
Thread.currentThread().interrupt();
}
} }
lastCall = System.currentTimeMillis(); } catch(InterruptedException e) {
if(!writer.writeFullFrame()) return; if(LOG.isLoggable(Level.INFO))
LOG.info("Interrupted while waiting to write frame");
Thread.currentThread().interrupt();
} }
} }
} }

View File

@@ -3,10 +3,12 @@ package net.sf.briar.transport;
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED; import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
import java.io.IOException; import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Mac; import javax.crypto.Mac;
import net.sf.briar.api.crypto.ErasableKey;
import net.sf.briar.api.crypto.ErasableKey;
import net.sf.briar.util.ByteUtils; import net.sf.briar.util.ByteUtils;
/** /**
@@ -17,6 +19,9 @@ import net.sf.briar.util.ByteUtils;
*/ */
class PaddedConnectionWriter extends ConnectionWriterImpl { class PaddedConnectionWriter extends ConnectionWriterImpl {
private static final Logger LOG =
Logger.getLogger(PaddedConnectionWriter.class.getName());
private final byte[] padding; private final byte[] padding;
private boolean closed = false; private boolean closed = false;
@@ -108,6 +113,8 @@ class PaddedConnectionWriter extends ConnectionWriterImpl {
try { try {
wait(); wait();
} catch(InterruptedException e) { } catch(InterruptedException e) {
if(LOG.isLoggable(Level.INFO))
LOG.info("Interrupted while waiting for space");
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
if(exception != null) throw exception; if(exception != null) throw exception;

View File

@@ -199,18 +199,18 @@ abstract class StreamConnection implements DatabaseListener {
dbExecutor.execute(new GenerateOffer()); dbExecutor.execute(new GenerateOffer());
// Main loop // Main loop
while(true) { while(true) {
try { Runnable task = writerTasks.take();
Runnable task = writerTasks.take(); if(task == CLOSE) break;
if(task == CLOSE) break; task.run();
task.run();
} catch(InterruptedException e) {
Thread.currentThread().interrupt();
}
} }
if(!disposed.getAndSet(true)) transport.dispose(true); if(!disposed.getAndSet(true)) transport.dispose(true);
} catch(DbException e) { } catch(DbException e) {
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage()); if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
if(!disposed.getAndSet(true)) transport.dispose(false); 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) { } catch(IOException e) {
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage()); if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
if(!disposed.getAndSet(true)) transport.dispose(false); if(!disposed.getAndSet(true)) transport.dispose(false);