Bug 94452 - Timeout exceptions

Bug 171075 comment 7 patch introduced the TimeoutException if the
current thread is interrupted while waiting on packet. Interesting that
the original version of the patch haven't this side effect, see bug
171075 comment 4. 

The proposal is to use original version of the patch, which does not
throw TimeoutException if the current thread is interrupted. 

The reasoning is: the VirtualMachineImpl which creates "receiveThread"
do not uses interrupt() to communicate cancellation or for any other
reason. The possibility to interrupt waiting on the debuggee VM via
<currentThread>.interrupt() in not documented and is not part of the
public contract of PacketReceiveManager, it is only used internally. The
internal use of interrupt() is in PacketManager.disconnectVM(), and the
effect of call is not affected by this patch because the wait condition
is evaluated to false via VMIsDisconnected() after this call.

The only possible other callers of <currentThread>.interrupt() are
outside of jdt debug, and they do if for different reasons as to stop
waiting on reply from the debuggee VM.

Therefore reacting on <currentThread>.interrupt() with TimeoutException
causes unexpected side effects, as one can see for example in multiple
duplicated bugs for bug 94452. Most of this bugs are side-effects of
trying to interrupt current job thread or the hover computation thread
of TextViewerHoverManager. Additionally, if the current thread is UI
thread, it will be also interrupted by calling UISynchronizer.syncExec()
from a non-UI thread. In all this cases we don't want to see
TimeoutException, getReply() can probably finish successfully without
exception (at least one can see it in the debugger).

One also should notice, that interrupting a thread in getReply() do not
interrupt actual debuggee execution task, which will still proceed, it
will only let getReply() return before timeout occurs. Default timeout
is 3000 ms, so in worst case the clients which do explicitly set timeout
will wait 3 seconds more. In case clients set longer timeouts they
usually do not want explicit thread termination (like
JDIThread.invokeMethod() which is ready to wait as long as needed).

Change-Id: If3aa16629c5fe1de29d3a05e0cfc0d614ad393e2
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
diff --git a/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/connect/PacketReceiveManager.java b/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/connect/PacketReceiveManager.java
index 81346c9..54423ac 100644
--- a/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/connect/PacketReceiveManager.java
+++ b/org.eclipse.jdt.debug/jdi/org/eclipse/jdi/internal/connect/PacketReceiveManager.java
@@ -21,6 +21,7 @@
 import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket;
 import org.eclipse.jdi.internal.jdwp.JdwpPacket;
 import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket;
+import org.eclipse.jdt.internal.debug.core.JDIDebugOptions;
 import org.eclipse.osgi.util.NLS;
 import com.sun.jdi.VMDisconnectedException;
@@ -29,7 +30,7 @@
  * This class implements a thread that receives packets from the Virtual
  * Machine.
- * 
+ *
 public class PacketReceiveManager extends PacketManager {
@@ -164,7 +165,12 @@
 				// see bug 171075
 				// just stop waiting for the reply and treat it as a timeout
 				catch (InterruptedException e) {
-					break;
+					if (JDIDebugOptions.DEBUG) {
+						JDIDebugOptions.trace(null, "Interrupt observed while waiting for packet: " + id, e); //$NON-NLS-1$
+					}
+					// Do not stop waiting on interrupt, this causes
+					// sporadic TimeoutException's without timeout
+					// break;
 				long waitedTime = System.currentTimeMillis() - timeBeforeWait;
 				remainingTime = timeToWait - waitedTime;
@@ -257,7 +263,7 @@
 	 * Returns whether the request for the given packet has already timed out.
-	 * 
+	 *
 	 * @param packet
 	 *            response packet
 	 * @return whether the request for the given packet has already timed out