summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpp/src/IceGrid/Activator.cpp71
-rw-r--r--cpp/src/IceGrid/Activator.h33
-rw-r--r--cpp/test/IceGrid/activation/AllTests.cpp72
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();
}
-