summaryrefslogtreecommitdiff
path: root/java/src/IceInternal/Connection.java
diff options
context:
space:
mode:
authorMarc Laukien <marc@zeroc.com>2003-12-08 20:19:04 +0000
committerMarc Laukien <marc@zeroc.com>2003-12-08 20:19:04 +0000
commitaf36567995055c5e4182274ef0f18f7a5767c04d (patch)
tree738efc51534b86497561b899154b3efd6a339123 /java/src/IceInternal/Connection.java
parentWinsock fix (diff)
downloadice-af36567995055c5e4182274ef0f18f7a5767c04d.tar.bz2
ice-af36567995055c5e4182274ef0f18f7a5767c04d.tar.xz
ice-af36567995055c5e4182274ef0f18f7a5767c04d.zip
deadlock fix
Diffstat (limited to 'java/src/IceInternal/Connection.java')
-rw-r--r--java/src/IceInternal/Connection.java73
1 files changed, 63 insertions, 10 deletions
diff --git a/java/src/IceInternal/Connection.java b/java/src/IceInternal/Connection.java
index 7ae84a19121..1fdfc68d39b 100644
--- a/java/src/IceInternal/Connection.java
+++ b/java/src/IceInternal/Connection.java
@@ -1107,21 +1107,58 @@ public final class Connection extends EventHandler
}
}
- public synchronized void
+ public void
finished(ThreadPool threadPool)
{
- threadPool.promoteFollower();
-
- if(_state == StateActive || _state == StateClosing)
+ IntMap requests = null;
+ IntMap asyncRequests = null;
+
+ synchronized(this)
+ {
+ threadPool.promoteFollower();
+
+ if(_state == StateActive || _state == StateClosing)
+ {
+ registerWithPool();
+ }
+ else if(_state == StateClosed && _transceiver != null)
+ {
+ _transceiver.close();
+ _transceiver = null;
+ _threadPool = null; // We don't need the thread pool anymore.
+ notifyAll();
+ }
+
+ if(_state == StateClosed || _state == StateClosing)
+ {
+ requests = _requests;
+ _requests = new IntMap();
+
+ asyncRequests = _asyncRequests;
+ _asyncRequests = new IntMap();
+ }
+ }
+
+ if(requests != null)
{
- registerWithPool();
+ java.util.Iterator i = requests.entryIterator();
+ while(i.hasNext())
+ {
+ IntMap.Entry e = (IntMap.Entry)i.next();
+ Outgoing out = (Outgoing)e.getValue();
+ out.finished(_exception); // Exception is immutable at this point.
+ }
}
- else if(_state == StateClosed && _transceiver != null)
+
+ if(asyncRequests != null)
{
- _transceiver.close();
- _transceiver = null;
- _threadPool = null; // We don't need the thread pool anymore.
- notifyAll();
+ java.util.Iterator i = asyncRequests.entryIterator();
+ while(i.hasNext())
+ {
+ IntMap.Entry e = (IntMap.Entry)i.next();
+ OutgoingAsync out = (OutgoingAsync)e.getValue();
+ out.__finished(_exception); // Exception is immutable at this point.
+ }
}
}
@@ -1194,6 +1231,12 @@ public final class Connection extends EventHandler
private void
setState(int state, Ice.LocalException ex)
{
+ //
+ // If setState() is called with an exception, then only closed
+ // and closing states are permissible.
+ //
+ assert(state == StateClosing || state == StateClosed);
+
if(_state == state) // Don't switch twice.
{
return;
@@ -1226,6 +1269,15 @@ public final class Connection extends EventHandler
//
setState(state);
+ //
+ // We can't call __finished() on async requests here, because
+ // it's possible that the callback will trigger another call,
+ // which then might block on this connection. Calling
+ // finished() at this place works for non-async calls, but in
+ // order to keep the logic of sending exceptions to requests
+ // in one place, we don't do this here either. Instead, we
+ // move all the code into the finished() operation.
+ /*
{
java.util.Iterator i = _requests.entryIterator();
while(i.hasNext())
@@ -1247,6 +1299,7 @@ public final class Connection extends EventHandler
}
_asyncRequests.clear();
}
+ */
}
private void