summaryrefslogtreecommitdiff
path: root/cpp/src/Ice/ConnectionFactory.cpp
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2017-01-18 19:16:02 +0100
committerBenoit Foucher <benoit@zeroc.com>2017-01-18 19:16:02 +0100
commit4baf696c7156c9f300a33d9041bd677c574b6e14 (patch)
tree15d736254302f6b01260134a97f3bdfc04ff9738 /cpp/src/Ice/ConnectionFactory.cpp
parentFixed bug introduced by previous commit (diff)
downloadice-4baf696c7156c9f300a33d9041bd677c574b6e14.tar.bz2
ice-4baf696c7156c9f300a33d9041bd677c574b6e14.tar.xz
ice-4baf696c7156c9f300a33d9041bd677c574b6e14.zip
Fixed ICE-2802 - no longer halt when running out of FDs
Diffstat (limited to 'cpp/src/Ice/ConnectionFactory.cpp')
-rw-r--r--cpp/src/Ice/ConnectionFactory.cpp96
1 files changed, 59 insertions, 37 deletions
diff --git a/cpp/src/Ice/ConnectionFactory.cpp b/cpp/src/Ice/ConnectionFactory.cpp
index 0aaa3b09bc1..755ab969003 100644
--- a/cpp/src/Ice/ConnectionFactory.cpp
+++ b/cpp/src/Ice/ConnectionFactory.cpp
@@ -126,6 +126,25 @@ find(const multimap<K,::IceInternal::Handle<V> >& m,
}
#endif
+class StartAcceptor : public IceUtil::TimerTask
+{
+public:
+
+ StartAcceptor(const IncomingConnectionFactoryPtr& factory) : _factory(factory)
+ {
+ }
+
+ void
+ runTimerTask()
+ {
+ _factory->startAcceptor();
+ }
+
+private:
+
+ IncomingConnectionFactoryPtr _factory;
+};
+
}
bool
@@ -1290,11 +1309,8 @@ IceInternal::IncomingConnectionFactory::startAsync(SocketOperation)
}
catch(const Ice::LocalException& ex)
{
- {
- Error out(_instance->initializationData().logger);
- out << "can't accept connections:\n" << ex << '\n' << _acceptor->toString();
- }
- abort();
+ ICE_SET_EXCEPTION_FROM_CLONE(_acceptorException, ex.ice_clone());
+ _acceptor->getNativeInfo()->completed(SocketOperationRead);
}
return true;
}
@@ -1305,13 +1321,22 @@ IceInternal::IncomingConnectionFactory::finishAsync(SocketOperation)
assert(_acceptor);
try
{
+ if(_acceptorException)
+ {
+ _acceptorException->ice_throw();
+ }
_acceptor->finishAccept();
}
catch(const LocalException& ex)
{
+ _acceptorException.reset(ICE_NULLPTR);
+
Error out(_instance->initializationData().logger);
out << "couldn't accept connection:\n" << ex << '\n' << _acceptor->toString();
- return false;
+ if(_adapter->getThreadPool()->finish(ICE_SHARED_FROM_THIS, true))
+ {
+ closeAcceptor();
+ }
}
return _state < StateClosed;
}
@@ -1353,7 +1378,7 @@ IceInternal::IncomingConnectionFactory::message(ThreadPoolCurrent& current)
_connections.erase(*p);
}
- if(!_acceptor)
+ if(!_acceptorStarted)
{
return;
}
@@ -1376,11 +1401,13 @@ IceInternal::IncomingConnectionFactory::message(ThreadPoolCurrent& current)
{
if(noMoreFds(ex.error))
{
+ Error out(_instance->initializationData().logger);
+ out << "can't accept more connections:\n" << ex << '\n' << _acceptor->toString();
+
+ if(_adapter->getThreadPool()->finish(ICE_SHARED_FROM_THIS, true))
{
- Error out(_instance->initializationData().logger);
- out << "fatal error: can't accept more connections:\n" << ex << '\n' << _acceptor->toString();
+ closeAcceptor();
}
- abort();
}
// Ignore socket exceptions.
@@ -1435,27 +1462,19 @@ void
IceInternal::IncomingConnectionFactory::finished(ThreadPoolCurrent&, bool close)
{
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
-
-#if TARGET_OS_IPHONE != 0
if(_state < StateClosed)
{
- //
- // Finished has been called by stopAcceptor if the state isn't
- // closed.
- //
if(_acceptorStarted && close)
{
- _acceptorStarted = false;
closeAcceptor();
}
return;
}
-#endif
assert(_state == StateClosed);
setState(StateFinished);
- if(close)
+ if(_acceptorStarted && close)
{
closeAcceptor();
}
@@ -1542,13 +1561,14 @@ IceInternal::IncomingConnectionFactory::IncomingConnectionFactory(const Instance
_instance(instance),
_monitor(new FactoryACMMonitor(instance, dynamic_cast<ObjectAdapterI*>(adapter.get())->getACM())),
_endpoint(endpoint),
+ _acceptorStarted(false),
+ _acceptorStopped(false),
_adapter(adapter),
_warn(_instance->initializationData().properties->getPropertyAsInt("Ice.Warn.Connections") > 0),
_state(StateHolding)
{
}
-#if TARGET_OS_IPHONE != 0
void
IceInternal::IncomingConnectionFactory::startAcceptor()
{
@@ -1558,18 +1578,17 @@ IceInternal::IncomingConnectionFactory::startAcceptor()
return;
}
+ _acceptorStopped = false;
+
try
{
createAcceptor();
- _acceptorStarted = true;
}
catch(const Ice::Exception& ex)
{
- if(_warn)
- {
- Warning out(_instance->initializationData().logger);
- out << "unable to create acceptor:\n" << ex;
- }
+ Error out(_instance->initializationData().logger);
+ out << "acceptor creation failed:\n" << ex << '\n' << _acceptor->toString();
+ _instance->timer()->schedule(ICE_MAKE_SHARED(StartAcceptor, ICE_SHARED_FROM_THIS), IceUtil::Time::seconds(1));
}
}
@@ -1582,13 +1601,13 @@ IceInternal::IncomingConnectionFactory::stopAcceptor()
return;
}
+ _acceptorStopped = true;
+
if(_adapter->getThreadPool()->finish(ICE_SHARED_FROM_THIS, true))
{
- _acceptorStarted = false;
closeAcceptor();
}
}
-#endif
void
IceInternal::IncomingConnectionFactory::initialize()
@@ -1625,7 +1644,6 @@ IceInternal::IncomingConnectionFactory::initialize()
// The notification center will call back on the factory to
// start the acceptor if necessary.
//
- _acceptorStarted = false;
registerForBackgroundNotification(ICE_SHARED_FROM_THIS);
#else
createAcceptor();
@@ -1709,7 +1727,7 @@ IceInternal::IncomingConnectionFactory::setState(State state)
case StateClosed:
{
- if(_acceptor)
+ if(_acceptorStarted)
{
//
// If possible, close the acceptor now to prevent new connections from
@@ -1749,6 +1767,7 @@ IceInternal::IncomingConnectionFactory::createAcceptor()
{
try
{
+ assert(!_acceptorStarted);
_acceptor = _endpoint->acceptor(_adapter->getName());
assert(_acceptor);
if(_instance->traceLevels()->network >= 2)
@@ -1769,13 +1788,14 @@ IceInternal::IncomingConnectionFactory::createAcceptor()
{
_adapter->getThreadPool()->_register(ICE_SHARED_FROM_THIS, SocketOperationRead);
}
+
+ _acceptorStarted = true;
}
catch(const Ice::Exception&)
{
if(_acceptor)
{
_acceptor->close();
- _acceptor = 0;
}
throw;
}
@@ -1792,14 +1812,16 @@ IceInternal::IncomingConnectionFactory::closeAcceptor()
out << "stopping to accept " << _endpoint->protocol() << " connections at " << _acceptor->toString();
}
+ _acceptorStarted = false;
_acceptor->close();
-#if TARGET_OS_IPHONE != 0
//
- // Only clear the acceptor on iOS where it can be destroyed/re-created during the lifetime of the incoming
- // connection factory. On other platforms, we keep it set. This is in particular import for IOCP/UWP where
- // finishAsync can be called after the acceptor is closed.
+ // If the acceptor hasn't been explicitly stopped (which is the case if the acceptor got closed
+ // because of an unexpected error), try to restart the acceptor in 5 seconds.
//
- _acceptor = 0;
-#endif
+ if(!_acceptorStopped && (_state == StateHolding || _state == StateActive))
+ {
+ _instance->timer()->schedule(ICE_MAKE_SHARED(StartAcceptor, ICE_SHARED_FROM_THIS), IceUtil::Time::seconds(1));
+ }
}
+