diff options
-rw-r--r-- | cpp/src/IceGrid/Activator.cpp | 71 | ||||
-rw-r--r-- | cpp/src/IceGrid/Activator.h | 33 | ||||
-rw-r--r-- | cpp/test/IceGrid/activation/AllTests.cpp | 72 |
3 files changed, 113 insertions, 63 deletions
diff --git a/cpp/src/IceGrid/Activator.cpp b/cpp/src/IceGrid/Activator.cpp index a7969d6fad9..6b06cbc3d5d 100644 --- a/cpp/src/IceGrid/Activator.cpp +++ b/cpp/src/IceGrid/Activator.cpp @@ -289,6 +289,14 @@ operator()(const wstring& lhs, const wstring& rhs) const } +#ifdef _WIN32 +extern "C" void CALLBACK activatorWaitCallback(PVOID data, BOOLEAN) +{ + Activator::Process* process = reinterpret_cast<Activator::Process*>(data); + process->activator->processTerminated(process); +} +#endif + Activator::Activator(const TraceLevelsPtr& traceLevels) : _traceLevels(traceLevels), _deactivating(false) @@ -599,16 +607,21 @@ Activator::activate(const string& name, // keep the thread handle, so we close it now. The process handle will be closed later. // CloseHandle(pi.hThread); - + process.activator = this; process.pid = pi.dwProcessId; process.hnd = pi.hProcess; process.server = server; - _processes.insert(make_pair(name, process)); + map<string, Process>::iterator it = _processes.insert(make_pair(name, process)).first; - setInterrupt(); + Process* pp = &it->second; + if(!RegisterWaitForSingleObject(&pp->waithnd, pp->hnd, activatorWaitCallback, pp, INFINITE, + WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE)) + { + throw IceUtilInternal::lastErrorToString(); + } // - // Don't print the following trace, this might interfere with the + // Don't print the following trace, this might interfer with the // output of the started process if it fails with an error message. // // if(_traceLevels->activator > 0) @@ -1146,51 +1159,30 @@ Activator::terminationListener() #ifdef _WIN32 while(true) { - vector<HANDLE> handles; - - // - // Lock while we collect the process handles. - // - { - IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); - - for(map<string, Process>::iterator p = _processes.begin(); p != _processes.end(); ++p) - { - handles.push_back(p->second.hnd); - } - } - - handles.push_back(_hIntr); - // - // Wait for a child to terminate, or the interrupt event to be signaled. + // Wait for the interrupt event to be signaled. // - DWORD ret = WaitForMultipleObjects(static_cast<DWORD>(handles.size()), &handles[0], FALSE, INFINITE); + DWORD ret = WaitForSingleObject(_hIntr, INFINITE); if(ret == WAIT_FAILED) { SyscallException ex(__FILE__, __LINE__); ex.error = getSystemErrno(); throw ex; } + clearInterrupt(); - vector<HANDLE>::size_type pos = ret - WAIT_OBJECT_0; - assert(pos < handles.size()); - HANDLE hnd = handles[pos]; - + // + // Collect terminated processes + // vector<Process> terminated; bool deactivated = false; { IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); - - if(hnd == _hIntr) - { - clearInterrupt(); - } - else + for(vector<Process*>::const_iterator q = _terminated.begin(); q != _terminated.end(); ++q) { for(map<string, Process>::iterator p = _processes.begin(); p != _processes.end(); ++p) { - if(p->second.hnd == hnd) + if(&p->second == *q) { terminated.push_back(p->second); _processes.erase(p); @@ -1198,14 +1190,17 @@ Activator::terminationListener() } } } - + _terminated.clear(); deactivated = _deactivating && _processes.empty(); } for(vector<Process>::const_iterator p = terminated.begin(); p != terminated.end(); ++p) { + UnregisterWait(p->waithnd); + DWORD status; GetExitCodeProcess(p->hnd, &status); + CloseHandle(p->hnd); assert(status != STILL_ACTIVE); @@ -1477,4 +1472,12 @@ Activator::waitPid(pid_t processPid) return -1; } } +#else +void +Activator::processTerminated(Activator::Process* process) +{ + IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); + setInterrupt(); + _terminated.push_back(process); +} #endif diff --git a/cpp/src/IceGrid/Activator.h b/cpp/src/IceGrid/Activator.h index 8e45f6c1209..5251e8ab91d 100644 --- a/cpp/src/IceGrid/Activator.h +++ b/cpp/src/IceGrid/Activator.h @@ -32,6 +32,21 @@ class Activator : public IceUtil::Monitor< IceUtil::Mutex>, public IceUtil::Shar { public: + struct Process + { +#ifdef _WIN32 + Activator* activator; + DWORD pid; + HANDLE hnd; + HANDLE waithnd; +#else + pid_t pid; + int pipeFd; + std::string msg; +#endif + ServerIPtr server; + }; + Activator(const TraceLevelsPtr&); virtual ~Activator(); @@ -56,6 +71,10 @@ public: void sendSignal(const std::string&, int); void runTerminationListener(); +#ifdef _WIN32 + void processTerminated(Process*); +#endif + private: void terminationListener(); @@ -66,25 +85,13 @@ private: int waitPid(pid_t); #endif - struct Process - { -#ifdef _WIN32 - DWORD pid; - HANDLE hnd; -#else - pid_t pid; - int pipeFd; - std::string msg; -#endif - ServerIPtr server; - }; - TraceLevelsPtr _traceLevels; std::map<std::string, Process> _processes; bool _deactivating; #ifdef _WIN32 HANDLE _hIntr; + std::vector<Process*> _terminated; #else int _fdIntrRead; int _fdIntrWrite; diff --git a/cpp/test/IceGrid/activation/AllTests.cpp b/cpp/test/IceGrid/activation/AllTests.cpp index b242d277ffb..369a79eead8 100644 --- a/cpp/test/IceGrid/activation/AllTests.cpp +++ b/cpp/test/IceGrid/activation/AllTests.cpp @@ -36,7 +36,7 @@ waitForServerState(const IceGrid::AdminPrx& admin, const std::string& server, Ic class PingThread : public IceUtil::Thread, IceUtil::Monitor<IceUtil::Mutex> { public: - + PingThread(const Ice::ObjectPrx& proxy, int nRepetitions) : _proxy(proxy), _finished(false), _nRepetitions(nRepetitions) { @@ -77,7 +77,7 @@ public: } private: - + Ice::ObjectPrx _proxy; IceUtil::UniquePtr<Ice::LocalException> _exception; bool _finished; @@ -154,7 +154,7 @@ allTests(const Ice::CommunicatorPtr& communicator) test(admin->getServerState("server-manual") == IceGrid::Inactive); admin->startServer("server-manual"); test(admin->getServerState("server-manual") == IceGrid::Active); - obj = TestIntfPrx::checkedCast(communicator->stringToProxy("server-manual")); + obj = TestIntfPrx::checkedCast(communicator->stringToProxy("server-manual")); test(admin->getServerState("server-manual") == IceGrid::Active); obj->shutdown(); waitForServerState(admin, "server-manual", IceGrid::Inactive); @@ -342,7 +342,7 @@ allTests(const Ice::CommunicatorPtr& communicator) test(false); } cout << "ok" << endl; - + cout << "testing server enable... " << flush; try @@ -392,7 +392,7 @@ allTests(const Ice::CommunicatorPtr& communicator) cerr << ex << endl; test(false); } - cout << "ok" << endl; + cout << "ok" << endl; cout << "testing activation failure... " << flush; try @@ -514,7 +514,7 @@ allTests(const Ice::CommunicatorPtr& communicator) cerr << ex << endl; test(false); } - cout << "ok" << endl; + cout << "ok" << endl; cout << "testing deactivation timeout... " << flush; try @@ -528,7 +528,7 @@ allTests(const Ice::CommunicatorPtr& communicator) cerr << ex << endl; test(false); } - cout << "ok" << endl; + cout << "ok" << endl; cout << "testing permanent disable on failure... " << flush; try @@ -540,18 +540,18 @@ allTests(const Ice::CommunicatorPtr& communicator) waitForServerState(admin, "server1", IceGrid::Inactive); try { - obj->ice_ping(); + obj->ice_ping(); test(false); } catch(const Ice::NoEndpointException&) { - } + } test(!admin->isServerEnabled("server1")); test(admin->getServerState("server1-manual") == IceGrid::Inactive); admin->startServer("server1-manual"); test(admin->getServerState("server1-manual") == IceGrid::Active); - obj = TestIntfPrx::checkedCast(communicator->stringToProxy("server1-manual")); + obj = TestIntfPrx::checkedCast(communicator->stringToProxy("server1-manual")); test(admin->getServerState("server1-manual") == IceGrid::Active); obj->fail(); waitForServerState(admin, "server1-manual", IceGrid::Inactive); @@ -568,7 +568,7 @@ allTests(const Ice::CommunicatorPtr& communicator) cerr << ex << endl; test(false); } - cout << "ok" << endl; + cout << "ok" << endl; cout << "testing temporary disable on failure... " << flush; @@ -581,12 +581,12 @@ allTests(const Ice::CommunicatorPtr& communicator) waitForServerState(admin, "server2", IceGrid::Inactive); try { - obj->ice_ping(); + obj->ice_ping(); test(false); } catch(const Ice::NoEndpointException&) { - } + } test(!admin->isServerEnabled("server2")); nRetry = 0; while(!admin->isServerEnabled("server2") && nRetry < 15) @@ -595,7 +595,7 @@ allTests(const Ice::CommunicatorPtr& communicator) ++nRetry; try { - obj->ice_ping(); + obj->ice_ping(); } catch(const Ice::NoEndpointException&) { @@ -641,9 +641,49 @@ allTests(const Ice::CommunicatorPtr& communicator) } cout << "ok" << endl; + cout << "testing large number of servers... " << flush; + { + IceGrid::ApplicationInfo info = admin->getApplicationInfo("Test"); + IceGrid::ApplicationDescriptor testApp; + testApp.name = "TestApp"; + testApp.serverTemplates = info.descriptor.serverTemplates; + testApp.variables = info.descriptor.variables; + for(int i = 0; i < 100; ++i) + { + ostringstream id; + id << "server-" << i; + IceGrid::ServerInstanceDescriptor server; + server._cpp_template = "Server"; + server.parameterValues["id"] = id.str(); + testApp.nodes["localnode"].serverInstances.push_back(server); + } + try + { + admin->addApplication(testApp); + } + catch(const IceGrid::DeploymentException& ex) + { + cerr << ex.reason << endl; + test(false); + } + for(int i = 0; i < 100; ++i) + { + ostringstream id; + id << "server-" << i; + admin->startServer(id.str()); + } + for(int i = 0; i < 100; ++i) + { + ostringstream id; + id << "server-" << i; + admin->stopServer(id.str()); + } + admin->removeApplication("TestApp"); + } + cout << "ok" << endl; + admin->stopServer("node-1"); admin->stopServer("node-2"); - + session->destroy(); } - |