From 0dde4162e6f6450a32d116b50c5e4f6e3435ac7c Mon Sep 17 00:00:00 2001 From: str4d Date: Sat, 23 Nov 2013 04:24:30 +0000 Subject: [PATCH 1/4] susimail: Fix NPE when deleting last message (ticket #414) --- apps/susimail/src/src/i2p/susi/webmail/WebMail.java | 13 +++++++++---- history.txt | 3 +++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/apps/susimail/src/src/i2p/susi/webmail/WebMail.java b/apps/susimail/src/src/i2p/susi/webmail/WebMail.java index 1bec8a72e..54e23c83e 100644 --- a/apps/susimail/src/src/i2p/susi/webmail/WebMail.java +++ b/apps/susimail/src/src/i2p/susi/webmail/WebMail.java @@ -1287,10 +1287,15 @@ public class WebMail extends HttpServlet if( sessionObject.state == STATE_SHOW ) { processMessageButtons( sessionObject, request ); - Mail mail = sessionObject.mailCache.getMail( sessionObject.showUIDL, MailCache.FETCH_ALL ); - if( mail != null && mail.error.length() > 0 ) { - sessionObject.error += mail.error; - mail.error = ""; + // If the last message has just been deleted then + // sessionObject.state = STATE_LIST and + // sessionObject.showUIDL = null + if ( sessionObject.showUIDL != null ) { + Mail mail = sessionObject.mailCache.getMail( sessionObject.showUIDL, MailCache.FETCH_ALL ); + if( mail != null && mail.error.length() > 0 ) { + sessionObject.error += mail.error; + mail.error = ""; + } } } diff --git a/history.txt b/history.txt index ec0641461..decffe34a 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,6 @@ +2013-11-23 str4d + * susimail: Fix NPE when deleting last message (ticket #414) + 2013-11-19 kytv * Translation updates and start of Japanese translation pulled from Transifex From fdb0097934320a60a57b50f24dd32ed5c749e6a5 Mon Sep 17 00:00:00 2001 From: str4d Date: Sat, 23 Nov 2013 11:44:07 +0000 Subject: [PATCH 2/4] Temporarily moved old help.jsp translations back --- .../jsp/{old-translations/help_ar.jsp.old => help_ar.jsp} | 0 .../jsp/{old-translations/help_fr.jsp.old => help_fr.jsp} | 0 .../jsp/{old-translations/help_nl.jsp.old => help_nl.jsp} | 0 .../jsp/{old-translations/help_ru.jsp.old => help_ru.jsp} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename apps/routerconsole/jsp/{old-translations/help_ar.jsp.old => help_ar.jsp} (100%) rename apps/routerconsole/jsp/{old-translations/help_fr.jsp.old => help_fr.jsp} (100%) rename apps/routerconsole/jsp/{old-translations/help_nl.jsp.old => help_nl.jsp} (100%) rename apps/routerconsole/jsp/{old-translations/help_ru.jsp.old => help_ru.jsp} (100%) diff --git a/apps/routerconsole/jsp/old-translations/help_ar.jsp.old b/apps/routerconsole/jsp/help_ar.jsp similarity index 100% rename from apps/routerconsole/jsp/old-translations/help_ar.jsp.old rename to apps/routerconsole/jsp/help_ar.jsp diff --git a/apps/routerconsole/jsp/old-translations/help_fr.jsp.old b/apps/routerconsole/jsp/help_fr.jsp similarity index 100% rename from apps/routerconsole/jsp/old-translations/help_fr.jsp.old rename to apps/routerconsole/jsp/help_fr.jsp diff --git a/apps/routerconsole/jsp/old-translations/help_nl.jsp.old b/apps/routerconsole/jsp/help_nl.jsp similarity index 100% rename from apps/routerconsole/jsp/old-translations/help_nl.jsp.old rename to apps/routerconsole/jsp/help_nl.jsp diff --git a/apps/routerconsole/jsp/old-translations/help_ru.jsp.old b/apps/routerconsole/jsp/help_ru.jsp similarity index 100% rename from apps/routerconsole/jsp/old-translations/help_ru.jsp.old rename to apps/routerconsole/jsp/help_ru.jsp From 54fb91ba8e8c5c9fc863984c3e7a031ef601c72c Mon Sep 17 00:00:00 2001 From: zzz Date: Sat, 23 Nov 2013 17:54:01 +0000 Subject: [PATCH 3/4] I2PTunnel: Call destroySocketManager() when replacing a client socket manager configured with i2cp.newDestOnResume, or a shared client. This prevents lots of orphaned StreamingTimer threads. There are still cases where these threads may stick around, when a tunnel is stopped but not restarted. We don't know in some cases when a tunnel could be restarted and when it can't. destroySocketManager() should always be called when discarding a SocketManager but i2ptunnel doesn't do that now. More to do, but this fixes the most common case of leaked threads. Related tickets: ##642 #961 --- .../java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java index 807818d44..2ba6acc11 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java @@ -263,6 +263,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna getTunnel().removeSession(sess); if (_log.shouldLog(Log.WARN)) _log.warn(getTunnel().getClientOptions().getProperty("inbound.nickname") + ": Built a new destination on resume"); + // make sure the old one is closed + sockMgr.destroySocketManager(); newManager = true; } // else the old socket manager will reconnect the old session if necessary } @@ -320,6 +322,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna if (_log.shouldLog(Log.INFO)) _log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Building a new socket manager since the old one closed [s=" + s + "]"); tunnel.removeSession(s); + // make sure the old one is closed + socketManager.destroySocketManager(); // We could be here a LONG time, holding the lock socketManager = buildSocketManager(tunnel, pkf); } else { From ffa03f2b8356cd36973ecaa78a421b4483c44548 Mon Sep 17 00:00:00 2001 From: zzz Date: Sat, 23 Nov 2013 17:56:40 +0000 Subject: [PATCH 4/4] IterativeSearchJob: - Recheck completion status just before sending out a wrapped message - log tweaks --- history.txt | 4 ++- .../src/net/i2p/router/RouterVersion.java | 2 +- .../kademlia/IterativeSearchJob.java | 26 ++++++++++++++----- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/history.txt b/history.txt index decffe34a..15e4be9ca 100644 --- a/history.txt +++ b/history.txt @@ -1,8 +1,10 @@ +2013-11-23 zzz + * i2ptunnel: Clean up old timer threads + 2013-11-23 str4d * susimail: Fix NPE when deleting last message (ticket #414) 2013-11-19 kytv - * Translation updates and start of Japanese translation pulled from Transifex 2013-11-14 kytv diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 5fd579e05..a06babd51 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 30; + public final static long BUILD = 31; /** for example "-test" */ public final static String EXTRA = "-rc"; diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/IterativeSearchJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/IterativeSearchJob.java index edc186954..868f0d0b8 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/IterativeSearchJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/IterativeSearchJob.java @@ -156,7 +156,7 @@ class IterativeSearchJob extends FloodSearchJob { _toTry.remove(_key); if (_toTry.isEmpty()) { if (_log.shouldLog(Log.WARN)) - _log.warn(getJobId() + ": Iterative search for " + _key + " had no peers to send to"); + _log.warn(getJobId() + ": ISJ for " + _key + " had no peers to send to"); // no floodfill peers, fail failed(); return; @@ -168,7 +168,9 @@ class IterativeSearchJob extends FloodSearchJob { Job onTimeout = new FloodOnlyLookupTimeoutJob(getContext(), this); _out = getContext().messageRegistry().registerPending(replySelector, onReply, onTimeout, _timeoutMs); if (_log.shouldLog(Log.INFO)) - _log.info(getJobId() + ": Iterative search for " + _key + " (rkey " + _rkey + ") timeout " + + _log.info(getJobId() + ": New ISJ for " + + (_isLease ? "LS " : "RI ") + + _key + " (rkey " + _rkey + ") timeout " + DataHelper.formatDuration(_timeoutMs) + " toTry: " + DataHelper.toString(_toTry)); retry(); } @@ -251,8 +253,13 @@ class IterativeSearchJob extends FloodSearchJob { dlm.setReplyTunnel(replyTunnel.getReceiveTunnelId(0)); dlm.setSearchKey(_key); - if (_log.shouldLog(Log.INFO)) - _log.info(getJobId() + ": Iterative search for " + _key + " to " + peer); + if (_log.shouldLog(Log.INFO)) { + int tries; + synchronized(this) { + tries = _unheardFrom.size() + _failedPeers.size(); + } + _log.info(getJobId() + ": ISJ try " + tries + " for " + _key + " to " + peer); + } long now = getContext().clock().now(); _sentTime.put(peer, Long.valueOf(now)); @@ -270,6 +277,13 @@ class IterativeSearchJob extends FloodSearchJob { dlm.setReplySession(sess.key, sess.tag); } outMsg = MessageWrapper.wrap(getContext(), dlm, ri); + // ElG can take a while so do a final check before we send it, + // a response may have come in. + if (_dead) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug(getJobId() + ": aborting send, finished while wrapping msg to " + peer); + return; + } if (_log.shouldLog(Log.DEBUG)) _log.debug(getJobId() + ": Encrypted DLM for " + _key + " to " + peer); } @@ -375,7 +389,7 @@ class IterativeSearchJob extends FloodSearchJob { long time = System.currentTimeMillis() - _created; if (_log.shouldLog(Log.INFO)) { long timeRemaining = _expiration - getContext().clock().now(); - _log.info(getJobId() + ": Iterative search for " + _key + " failed with " + timeRemaining + " remaining after " + time + + _log.info(getJobId() + ": ISJ for " + _key + " failed with " + timeRemaining + " remaining after " + time + ", peers queried: " + tries); } getContext().statManager().addRateData("netDb.failedTime", time, 0); @@ -410,7 +424,7 @@ class IterativeSearchJob extends FloodSearchJob { } long time = System.currentTimeMillis() - _created; if (_log.shouldLog(Log.INFO)) - _log.info(getJobId() + ": Iterative search for " + _key + " successful after " + time + + _log.info(getJobId() + ": ISJ for " + _key + " successful after " + time + ", peers queried: " + tries); getContext().statManager().addRateData("netDb.successTime", time, 0); getContext().statManager().addRateData("netDb.successRetries", tries - 1, 0);