3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-15 19:55:51 +00:00

Clean up exception handling in Peer/PeerGroup. Resolves issue 65

This commit is contained in:
Miron Cuperman (devrandom) 2011-07-28 19:22:56 +00:00
parent 0d085606df
commit dfad026523
3 changed files with 65 additions and 27 deletions

View File

@ -92,14 +92,16 @@ public class Peer {
/** /**
* Connects to the peer. * Connects to the peer.
*
* @throws PeerException when there is a temporary problem with the peer and we should retry later
*/ */
public void connect() { public void connect() throws PeerException {
try { try {
conn = new NetworkConnection(address, params, bestHeight, 60000); conn = new NetworkConnection(address, params, bestHeight, 60000);
} catch (IOException ex) { } catch (IOException ex) {
throw new RuntimeException(ex); throw new PeerException(ex);
} catch (ProtocolException ex) { } catch (ProtocolException ex) {
throw new RuntimeException(ex); throw new PeerException(ex);
} }
} }
@ -107,13 +109,16 @@ public class Peer {
* Runs in the peers network loop and manages communication with the peer. * Runs in the peers network loop and manages communication with the peer.
* *
* <p>connect() must be called first * <p>connect() must be called first
*
* @throws PeerException when there is a temporary problem with the peer and we should retry later
*/ */
public void run() { public void run() throws PeerException {
// This should be called in the network loop thread for this peer // This should be called in the network loop thread for this peer
if (conn == null) if (conn == null)
throw new RuntimeException("please call connect() first"); throw new RuntimeException("please call connect() first");
running = true; running = true;
try { try {
while (true) { while (true) {
Message m = conn.readMessage(); Message m = conn.readMessage();
@ -130,25 +135,24 @@ public class Peer {
log.warn("Received unhandled message: {}", m); log.warn("Received unhandled message: {}", m);
} }
} }
} catch (Exception e) { } catch (IOException e) {
if (e instanceof IOException && !running) { disconnect();
if (!running) {
// This exception was expected because we are tearing down the socket as part of quitting. // This exception was expected because we are tearing down the socket as part of quitting.
log.info("Shutting down peer loop"); log.info("Shutting down peer loop");
} else { } else {
// We caught an unexpected exception. throw new PeerException(e);
e.printStackTrace();
} }
} catch (ProtocolException e) {
disconnect();
throw new PeerException(e);
} catch (RuntimeException e) {
disconnect();
log.error("unexpected exception in peer loop", e);
throw e;
} }
try { disconnect();
conn.shutdown();
} catch (IOException e) {
// Ignore exceptions on shutdown, socket might be dead
}
synchronized (this) {
running = false;
}
} }
private void processBlock(Block m) throws IOException { private void processBlock(Block m) throws IOException {
@ -383,7 +387,7 @@ public class Peer {
if (chainHeight <= 0) { if (chainHeight <= 0) {
// This should not happen because we shouldn't have given the user a Peer that is to another client-mode // This should not happen because we shouldn't have given the user a Peer that is to another client-mode
// node. If that happens it means the user overrode us somewhere. // node. If that happens it means the user overrode us somewhere.
throw new RuntimeException("Peer does not have block chain"); return -1;
} }
int blocksToGet = chainHeight - blockChain.getChainHead().getHeight(); int blocksToGet = chainHeight - blockChain.getChainHead().getHeight();
return blocksToGet; return blocksToGet;
@ -398,6 +402,7 @@ public class Peer {
} }
try { try {
// This is the correct way to stop an IO bound loop // This is the correct way to stop an IO bound loop
if (conn != null)
conn.shutdown(); conn.shutdown();
} catch (IOException e) { } catch (IOException e) {
// Don't care about this. // Don't care about this.

View File

@ -0,0 +1,36 @@
/**
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.bitcoin.core;
/**
* Thrown when a problem occurs in communicating with a peer, and we should
* retry.
*/
public class PeerException extends Exception {
@SuppressWarnings("serial")
public PeerException(String msg) {
super(msg);
}
public PeerException(Exception e) {
super(e);
}
public PeerException(String msg, Exception e) {
super(msg, e);
}
}

View File

@ -25,6 +25,7 @@ import com.google.bitcoin.store.BlockStoreException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOError;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.Collections; import java.util.Collections;
@ -242,17 +243,13 @@ public class PeerGroup {
handleNewPeer(peer); handleNewPeer(peer);
log.info("running " + peer); log.info("running " + peer);
peer.run(); peer.run();
} catch (RuntimeException ex) { } catch (PeerException ex) {
// do not propagate RuntimeException - log and try next peer // do not propagate PeerException - log and try next peer
log.error("error while talking to peer", ex); log.error("error while talking to peer", ex);
} finally { } finally {
// In all cases, disconnect and put the address back on the queue. // In all cases, disconnect and put the address back on the queue.
// We will retry this peer after all other peers have been tried. // We will retry this peer after all other peers have been tried.
try {
peer.disconnect(); peer.disconnect();
} catch (RuntimeException ex) {
// ignore
}
inactives.add(address); inactives.add(address);
if (peers.remove(peer)) if (peers.remove(peer))
@ -273,7 +270,7 @@ public class PeerGroup {
// Fatal error // Fatal error
log.error("Block store corrupt?", e); log.error("Block store corrupt?", e);
running = false; running = false;
break; throw new IOError(e);
} }
// If we got here, we should retry this address because an error unrelated // If we got here, we should retry this address because an error unrelated