summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2009-10-13 13:49:34 +0200
committerBenoit Foucher <benoit@zeroc.com>2009-10-13 13:49:34 +0200
commit50b781e9afffd5f2df09efb0a414c877afc74e95 (patch)
treef81ee8f7738dba72fc54edf636eeabbb5deb47b7 /cpp
parentFixed bug 4266 - stringified proxy issues, other minor issues (diff)
downloadice-50b781e9afffd5f2df09efb0a414c877afc74e95.tar.bz2
ice-50b781e9afffd5f2df09efb0a414c877afc74e95.tar.xz
ice-50b781e9afffd5f2df09efb0a414c877afc74e95.zip
Fixed bug 860 - close timeouts
Diffstat (limited to 'cpp')
-rw-r--r--cpp/src/Ice/ConnectionI.cpp96
-rw-r--r--cpp/src/Ice/ConnectionI.h1
-rw-r--r--cpp/src/Ice/DefaultsAndOverrides.cpp9
-rw-r--r--cpp/src/Ice/DefaultsAndOverrides.h3
-rw-r--r--cpp/src/Ice/PropertyNames.cpp3
-rw-r--r--cpp/src/Ice/PropertyNames.h2
-rw-r--r--cpp/test/Ice/timeout/AllTests.cpp42
7 files changed, 102 insertions, 54 deletions
diff --git a/cpp/src/Ice/ConnectionI.cpp b/cpp/src/Ice/ConnectionI.cpp
index 94303438497..7ae7476e306 100644
--- a/cpp/src/Ice/ConnectionI.cpp
+++ b/cpp/src/Ice/ConnectionI.cpp
@@ -356,59 +356,16 @@ Ice::ConnectionI::waitUntilFinished()
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
//
- // We wait indefinitely until connection closing has been
- // initiated. We also wait indefinitely until all outstanding
- // requests are completed. Otherwise we couldn't guarantee
- // that there are no outstanding calls when deactivate() is
- // called on the servant locators.
+ // We wait indefinitely until the connection is finished and all
+ // outstanding requests are completed. Otherwise we couldn't
+ // guarantee that there are no outstanding calls when deactivate()
+ // is called on the servant locators.
//
- while(_state < StateClosing || _dispatchCount > 0)
+ while(_state < StateFinished || _dispatchCount > 0)
{
wait();
}
- //
- // Now we must wait until close() has been called on the
- // transceiver.
- //
- while(_state != StateFinished)
- {
- if(_state < StateClosed && _endpoint->timeout() >= 0)
- {
- IceUtil::Time timeout = IceUtil::Time::milliSeconds(_endpoint->timeout());
- IceUtil::Time waitTime = _stateTime + timeout - IceUtil::Time::now(IceUtil::Time::Monotonic);
-
- if(waitTime > IceUtil::Time())
- {
- //
- // We must wait a bit longer until we close this
- // connection.
- //
- if(!timedWait(waitTime))
- {
- setState(StateClosed, CloseTimeoutException(__FILE__, __LINE__));
- }
- }
- else
- {
- //
- // We already waited long enough, so let's close this
- // connection!
- //
- setState(StateClosed, CloseTimeoutException(__FILE__, __LINE__));
- }
-
- //
- // No return here, we must still wait until close() is
- // called on the _transceiver.
- //
- }
- else
- {
- wait();
- }
- }
-
assert(_state == StateFinished);
//
@@ -1447,10 +1404,14 @@ Ice::ConnectionI::timedOut()
{
setState(StateClosed, ConnectTimeoutException(__FILE__, __LINE__));
}
- else if(_state <= StateClosing)
+ else if(_state < StateClosing)
{
setState(StateClosed, TimeoutException(__FILE__, __LINE__));
}
+ else if(_state == StateClosing)
+ {
+ setState(StateClosed, CloseTimeoutException(__FILE__, __LINE__));
+ }
}
string
@@ -1469,7 +1430,7 @@ ConnectionInfoPtr
Ice::ConnectionI::getInfo() const
{
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
- if(_exception.get())
+ if(_state >= StateClosed)
{
_exception->ice_throw();
}
@@ -1867,8 +1828,16 @@ Ice::ConnectionI::initiateShutdown()
os.write(headerSize); // Message size.
OutgoingMessage message(&os, false);
- sendMessage(message);
-
+ if(sendMessage(message))
+ {
+ //
+ // Schedule the close timeout to wait for the peer to close the connection. If
+ // the message was queued for sending, sendNextMessage will schedule the timeout
+ // once all messages were sent.
+ //
+ scheduleTimeout(SocketOperationWrite, closeTimeout());
+ }
+
//
// The CloseConnection message should be sufficient. Closing the write
// end of the socket is probably an artifact of how things were done
@@ -2123,6 +2092,15 @@ Ice::ConnectionI::sendNextMessage(vector<OutgoingAsyncMessageCallbackPtr>& callb
assert(_writeStream.b.empty());
_threadPool->unregister(this, SocketOperationWrite);
+
+ //
+ // If all the messages were sent and we are in the closing state, we schedule
+ // the close timeout to wait for the peer to close the connection.
+ //
+ if(_state == StateClosing)
+ {
+ scheduleTimeout(SocketOperationWrite, closeTimeout());
+ }
}
bool
@@ -2660,3 +2638,17 @@ Ice::ConnectionI::connectTimeout()
return _endpoint->timeout();
}
}
+
+int
+Ice::ConnectionI::closeTimeout()
+{
+ DefaultsAndOverridesPtr defaultsAndOverrides = _instance->defaultsAndOverrides();
+ if(defaultsAndOverrides->overrideCloseTimeout)
+ {
+ return defaultsAndOverrides->overrideCloseTimeoutValue;
+ }
+ else
+ {
+ return _endpoint->timeout();
+ }
+}
diff --git a/cpp/src/Ice/ConnectionI.h b/cpp/src/Ice/ConnectionI.h
index c13ae288561..a023767a63f 100644
--- a/cpp/src/Ice/ConnectionI.h
+++ b/cpp/src/Ice/ConnectionI.h
@@ -251,6 +251,7 @@ private:
}
int connectTimeout();
+ int closeTimeout();
const IceInternal::TransceiverPtr _transceiver;
const IceInternal::InstancePtr _instance;
diff --git a/cpp/src/Ice/DefaultsAndOverrides.cpp b/cpp/src/Ice/DefaultsAndOverrides.cpp
index b14686121da..81572b0ec68 100644
--- a/cpp/src/Ice/DefaultsAndOverrides.cpp
+++ b/cpp/src/Ice/DefaultsAndOverrides.cpp
@@ -23,6 +23,8 @@ IceInternal::DefaultsAndOverrides::DefaultsAndOverrides(const PropertiesPtr& pro
overrideTimeoutValue(-1),
overrideConnectTimeout(false),
overrideConnectTimeoutValue(-1),
+ overrideCloseTimeout(false),
+ overrideCloseTimeoutValue(-1),
overrideCompress(false),
overrideCompressValue(false),
overrideSecure(false),
@@ -48,6 +50,13 @@ IceInternal::DefaultsAndOverrides::DefaultsAndOverrides(const PropertiesPtr& pro
const_cast<Int&>(overrideConnectTimeoutValue) = properties->getPropertyAsInt("Ice.Override.ConnectTimeout");
}
+ value = properties->getProperty("Ice.Override.CloseTimeout");
+ if(!value.empty())
+ {
+ const_cast<bool&>(overrideCloseTimeout) = true;
+ const_cast<Int&>(overrideCloseTimeoutValue) = properties->getPropertyAsInt("Ice.Override.CloseTimeout");
+ }
+
value = properties->getProperty("Ice.Override.Compress");
if(!value.empty())
{
diff --git a/cpp/src/Ice/DefaultsAndOverrides.h b/cpp/src/Ice/DefaultsAndOverrides.h
index 1ee79794569..fb6b5d0bda7 100644
--- a/cpp/src/Ice/DefaultsAndOverrides.h
+++ b/cpp/src/Ice/DefaultsAndOverrides.h
@@ -1,3 +1,4 @@
+
// **********************************************************************
//
// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
@@ -35,6 +36,8 @@ public:
Ice::Int overrideTimeoutValue;
bool overrideConnectTimeout;
Ice::Int overrideConnectTimeoutValue;
+ bool overrideCloseTimeout;
+ Ice::Int overrideCloseTimeoutValue;
bool overrideCompress;
bool overrideCompressValue;
bool overrideSecure;
diff --git a/cpp/src/Ice/PropertyNames.cpp b/cpp/src/Ice/PropertyNames.cpp
index 1bd4149202e..e0b3f489e07 100644
--- a/cpp/src/Ice/PropertyNames.cpp
+++ b/cpp/src/Ice/PropertyNames.cpp
@@ -8,7 +8,7 @@
// **********************************************************************
//
-// Generated by makeprops.py from file ../config/PropertyNames.xml, Wed Oct 7 14:30:37 2009
+// Generated by makeprops.py from file ../config/PropertyNames.xml, Mon Oct 12 16:01:09 2009
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -80,6 +80,7 @@ const IceInternal::Property IcePropsData[] =
IceInternal::Property("Ice.MonitorConnections", false, 0),
IceInternal::Property("Ice.Nohup", false, 0),
IceInternal::Property("Ice.NullHandleAbort", false, 0),
+ IceInternal::Property("Ice.Override.CloseTimeout", false, 0),
IceInternal::Property("Ice.Override.Compress", false, 0),
IceInternal::Property("Ice.Override.ConnectTimeout", false, 0),
IceInternal::Property("Ice.Override.Timeout", false, 0),
diff --git a/cpp/src/Ice/PropertyNames.h b/cpp/src/Ice/PropertyNames.h
index 0c461df437a..1cd38a5c35e 100644
--- a/cpp/src/Ice/PropertyNames.h
+++ b/cpp/src/Ice/PropertyNames.h
@@ -8,7 +8,7 @@
// **********************************************************************
//
-// Generated by makeprops.py from file ../config/PropertyNames.xml, Wed Oct 7 14:30:37 2009
+// Generated by makeprops.py from file ../config/PropertyNames.xml, Mon Oct 12 16:01:09 2009
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
diff --git a/cpp/test/Ice/timeout/AllTests.cpp b/cpp/test/Ice/timeout/AllTests.cpp
index 698ddd3f24f..a0cf7a83178 100644
--- a/cpp/test/Ice/timeout/AllTests.cpp
+++ b/cpp/test/Ice/timeout/AllTests.cpp
@@ -283,6 +283,34 @@ allTests(const Ice::CommunicatorPtr& communicator)
}
cout << "ok" << endl;
+ cout << "testing close timeout... " << flush;
+ {
+ TimeoutPrx to = TimeoutPrx::checkedCast(obj->ice_timeout(250));
+ Ice::ConnectionPtr connection = to->ice_getConnection();
+ timeout->holdAdapter(750);
+ connection->close(false);
+ try
+ {
+ connection->getInfo(); // getInfo() doesn't throw in the closing state.
+ }
+ catch(const Ice::LocalException&)
+ {
+ test(false);
+ }
+ IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(300));
+ try
+ {
+ connection->getInfo();
+ test(false);
+ }
+ catch(const Ice::CloseConnectionException&)
+ {
+ // Expected.
+ }
+ timeout->op(); // Ensure adapter is active.
+ }
+ cout << "ok" << endl;
+
cout << "testing timeout overrides... " << flush;
{
//
@@ -368,6 +396,20 @@ allTests(const Ice::CommunicatorPtr& communicator)
}
comm->destroy();
}
+ {
+ //
+ // Test Ice.Override.CloseTimeout.
+ //
+ Ice::InitializationData initData;
+ initData.properties = communicator->getProperties()->clone();
+ initData.properties->setProperty("Ice.Override.CloseTimeout", "200");
+ Ice::CommunicatorPtr comm = Ice::initialize(initData);
+ Ice::ConnectionPtr connection = comm->stringToProxy(sref)->ice_getConnection();
+ timeout->holdAdapter(750);
+ IceUtil::Time now = IceUtil::Time::now();
+ comm->destroy();
+ test(IceUtil::Time::now() - now < IceUtil::Time::milliSeconds(500));
+ }
cout << "ok" << endl;
return timeout;