diff --git a/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketFull.java b/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketFull.java index abca9b82fc79f184ee8b507f6369f511bf4012aa..95d551d7382b655d096af9381df713eab4532f1d 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketFull.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketFull.java @@ -4,29 +4,41 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.channels.SelectableChannel; +import java.util.concurrent.atomic.AtomicBoolean; +import net.i2p.I2PAppContext; import net.i2p.client.I2PSession; import net.i2p.data.Destination; +import net.i2p.util.Log; /** * Bridge between the full streaming lib and the I2PSocket API * */ class I2PSocketFull implements I2PSocket { - private Connection _connection; - private Destination _remotePeer; - private Destination _localPeer; + private final Log log; + private volatile Connection _connection; + private final Destination _remotePeer; + private final Destination _localPeer; private volatile MessageChannel _channel; + private final AtomicBoolean _closed = new AtomicBoolean(false); - public I2PSocketFull(Connection con) { + public I2PSocketFull(Connection con, I2PAppContext context) { + log = context.logManager().getLog(I2PSocketFull.class); _connection = con; if (con != null) { _remotePeer = con.getRemotePeer(); _localPeer = con.getSession().getMyDestination(); - } + } else + _remotePeer = _localPeer = null; } public void close() throws IOException { + if (!_closed.compareAndSet(false,true)) { + // log a trace to find out why + LogUtil.logCloseLoop(log, "I2PSocket",_localPeer,"-->",_remotePeer,_connection); + return; + } Connection c = _connection; if (c == null) return; if (c.getIsConnected()) { diff --git a/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java b/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java index 83f170d84f8f5e3d8ba92342d75e4e839931a8d3..a60888f2cc6d74a8d9152b29aad559436d4c4072 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java @@ -316,10 +316,7 @@ public class I2PSocketManagerFull implements I2PSocketManager { public void destroySocketManager() { if (!_isDestroyed.compareAndSet(false,true)) { // shouldn't happen, log a stack trace to find out why it happened - if (_log.shouldLog(Log.WARN)) { - String log = "over-destroying manager "+getName(); - _log.log(Log.WARN,log,new Exception("check stack trace")); - } + LogUtil.logCloseLoop(_log, "I2PSocketManager", getName()); return; } _connectionManager.setAllowIncomingConnections(false); diff --git a/apps/streaming/java/src/net/i2p/client/streaming/LogUtil.java b/apps/streaming/java/src/net/i2p/client/streaming/LogUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..27d4752700a4a8b2b028d00e91dc4245c01b7e9e --- /dev/null +++ b/apps/streaming/java/src/net/i2p/client/streaming/LogUtil.java @@ -0,0 +1,37 @@ +package net.i2p.client.streaming; + +import net.i2p.util.Log; + +class LogUtil { + private LogUtil() {} + + /** + * logs a loop when closing a resource with level WARN + * @param desc vararg description + * @param log logger for the class we're intersted in + */ + static void logCloseLoop(Log log, Object... desc) { + logCloseLoop(log, Log.WARN, desc); + } + + /** + * Logs a close loop when closing a resource + * @param desc vararg description of the resource + * @param log logger to use + * @param level level at which to log + */ + static void logCloseLoop(Log log, int level, Object... desc) { + if (!log.shouldLog(level)) + return; + + // catenate all toString()s + String descString = "close() loop in"; + for (Object o : desc) { + descString += " "; + descString += String.valueOf(o); + } + + Exception e = new Exception("check stack trace"); + log.log(level,descString,e); + } +}