diff options
author | Benoit Foucher <benoit@zeroc.com> | 2017-01-18 19:16:02 +0100 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2017-01-18 19:16:02 +0100 |
commit | 4baf696c7156c9f300a33d9041bd677c574b6e14 (patch) | |
tree | 15d736254302f6b01260134a97f3bdfc04ff9738 /cpp/src/Ice/ConnectionFactory.cpp | |
parent | Fixed bug introduced by previous commit (diff) | |
download | ice-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.cpp | 96 |
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)); + } } + |