summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
authorMatthew Newhook <matthew@zeroc.com>2006-12-22 18:52:53 +0000
committerMatthew Newhook <matthew@zeroc.com>2006-12-22 18:52:53 +0000
commit84d9f5c369fceccfa16401ed50783ed2ad209559 (patch)
tree689d30c8707629f1db8155edadb47ce1bce363ad /cpp
parentAdded autoflushing of batches (diff)
downloadice-84d9f5c369fceccfa16401ed50783ed2ad209559.tar.bz2
ice-84d9f5c369fceccfa16401ed50783ed2ad209559.tar.xz
ice-84d9f5c369fceccfa16401ed50783ed2ad209559.zip
http://bugzilla.zeroc.com/bugzilla/show_bug.cgi?id=1391.
Diffstat (limited to 'cpp')
-rw-r--r--cpp/demo/Freeze/bench/Client.cpp13
-rw-r--r--cpp/demo/Freeze/library/Client.cpp25
-rw-r--r--cpp/demo/Freeze/library/Collocated.cpp25
-rw-r--r--cpp/demo/Freeze/phonebook/Client.cpp26
-rw-r--r--cpp/demo/Freeze/phonebook/Collocated.cpp25
-rw-r--r--cpp/demo/Glacier2/callback/Client.cpp25
-rwxr-xr-xcpp/demo/Glacier2/chat/Client.cpp97
-rw-r--r--cpp/demo/Ice/callback/Client.cpp25
-rw-r--r--cpp/demo/Ice/converter/Client.cpp5
-rw-r--r--cpp/demo/Ice/hello/Client.cpp25
-rw-r--r--cpp/demo/Ice/invoke/Client.cpp25
-rw-r--r--cpp/demo/Ice/nested/Client.cpp32
-rwxr-xr-xcpp/demo/Ice/session/Client.cpp96
-rw-r--r--cpp/demo/Ice/throughput/Client.cpp25
-rw-r--r--cpp/demo/Ice/value/Client.cpp25
-rw-r--r--cpp/demo/IceBox/hello/Client.cpp25
-rw-r--r--cpp/demo/IceGrid/allocate/Client.cpp121
-rw-r--r--cpp/demo/IceGrid/sessionActivation/Client.cpp113
-rw-r--r--cpp/demo/IceGrid/simple/Client.cpp24
-rw-r--r--cpp/include/Ice/Application.h12
-rw-r--r--cpp/src/Ice/Application.cpp110
21 files changed, 772 insertions, 127 deletions
diff --git a/cpp/demo/Freeze/bench/Client.cpp b/cpp/demo/Freeze/bench/Client.cpp
index e0e70dac728..e0aaab24e2a 100644
--- a/cpp/demo/Freeze/bench/Client.cpp
+++ b/cpp/demo/Freeze/bench/Client.cpp
@@ -144,6 +144,7 @@ public:
TestApp(const string&);
virtual int run(int, char*[]);
+ virtual void interruptCallback(int);
private:
@@ -717,6 +718,12 @@ typedef IceUtil::Handle<MyFactory> MyFactoryPtr;
int
TestApp::run(int argc, char* argv[])
{
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
_connection = Freeze::createConnection(communicator(), _envName);
cout << "IntIntMap" << endl;
@@ -810,6 +817,12 @@ TestApp::run(int argc, char* argv[])
return EXIT_SUCCESS;
}
+void
+TestApp::interruptCallback(int)
+{
+ exit(EXIT_SUCCESS);
+}
+
int
main(int argc, char* argv[])
{
diff --git a/cpp/demo/Freeze/library/Client.cpp b/cpp/demo/Freeze/library/Client.cpp
index dab9aaa2607..f43eeedf738 100644
--- a/cpp/demo/Freeze/library/Client.cpp
+++ b/cpp/demo/Freeze/library/Client.cpp
@@ -15,6 +15,7 @@ using namespace std;
class LibraryClient : public Ice::Application
{
virtual int run(int argc, char* argv[]);
+ virtual void interruptCallback(int);
};
int
@@ -27,6 +28,30 @@ main(int argc, char* argv[])
int
LibraryClient::run(int argc, char* argv[])
{
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
int runParser(int, char*[], const Ice::CommunicatorPtr&);
return runParser(argc, argv, communicator());
}
+
+void
+LibraryClient::interruptCallback(int)
+{
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+}
diff --git a/cpp/demo/Freeze/library/Collocated.cpp b/cpp/demo/Freeze/library/Collocated.cpp
index 4283dce2ef8..2d6fceb20e2 100644
--- a/cpp/demo/Freeze/library/Collocated.cpp
+++ b/cpp/demo/Freeze/library/Collocated.cpp
@@ -24,6 +24,7 @@ public:
}
virtual int run(int argc, char* argv[]);
+ virtual void interruptCallback(int);
private:
@@ -40,6 +41,12 @@ main(int argc, char* argv[])
int
LibraryCollocated::run(int argc, char* argv[])
{
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
Ice::PropertiesPtr properties = communicator()->getProperties();
//
@@ -84,3 +91,21 @@ LibraryCollocated::run(int argc, char* argv[])
return status;
}
+
+void
+LibraryCollocated::interruptCallback(int)
+{
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+}
diff --git a/cpp/demo/Freeze/phonebook/Client.cpp b/cpp/demo/Freeze/phonebook/Client.cpp
index 625041380a5..2478d5f7429 100644
--- a/cpp/demo/Freeze/phonebook/Client.cpp
+++ b/cpp/demo/Freeze/phonebook/Client.cpp
@@ -11,9 +11,11 @@
using namespace std;
+
class PhoneBookClient : public Ice::Application
{
virtual int run(int argc, char* argv[]);
+ virtual void interruptCallback(int);
};
int
@@ -26,6 +28,30 @@ main(int argc, char* argv[])
int
PhoneBookClient::run(int argc, char* argv[])
{
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
int runParser(int, char*[], const Ice::CommunicatorPtr&);
return runParser(argc, argv, communicator());
}
+
+void
+PhoneBookClient::interruptCallback(int)
+{
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+}
diff --git a/cpp/demo/Freeze/phonebook/Collocated.cpp b/cpp/demo/Freeze/phonebook/Collocated.cpp
index cb213a9da87..e979700f651 100644
--- a/cpp/demo/Freeze/phonebook/Collocated.cpp
+++ b/cpp/demo/Freeze/phonebook/Collocated.cpp
@@ -24,6 +24,7 @@ public:
}
virtual int run(int argc, char* argv[]);
+ virtual void interruptCallback(int);
private:
@@ -40,6 +41,12 @@ main(int argc, char* argv[])
int
PhoneBookCollocated::run(int argc, char* argv[])
{
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
Ice::PropertiesPtr properties = communicator()->getProperties();
//
@@ -101,3 +108,21 @@ PhoneBookCollocated::run(int argc, char* argv[])
return status;
}
+
+void
+PhoneBookCollocated::interruptCallback(int)
+{
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+}
diff --git a/cpp/demo/Glacier2/callback/Client.cpp b/cpp/demo/Glacier2/callback/Client.cpp
index 42e32317fe1..54a391b24ef 100644
--- a/cpp/demo/Glacier2/callback/Client.cpp
+++ b/cpp/demo/Glacier2/callback/Client.cpp
@@ -19,6 +19,7 @@ class CallbackClient : public Ice::Application
public:
virtual int run(int, char*[]);
+ virtual void interruptCallback(int);
};
int
@@ -47,6 +48,12 @@ menu()
int
CallbackClient::run(int argc, char* argv[])
{
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
Ice::RouterPrx defaultRouter = communicator()->getDefaultRouter();
if(!defaultRouter)
{
@@ -208,3 +215,21 @@ CallbackClient::run(int argc, char* argv[])
return EXIT_SUCCESS;
}
+
+void
+CallbackClient::interruptCallback(int)
+{
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+}
diff --git a/cpp/demo/Glacier2/chat/Client.cpp b/cpp/demo/Glacier2/chat/Client.cpp
index 59cedc50e6b..5c4c8dccb05 100755
--- a/cpp/demo/Glacier2/chat/Client.cpp
+++ b/cpp/demo/Glacier2/chat/Client.cpp
@@ -93,16 +93,23 @@ public:
virtual int
run(int argc, char* argv[])
{
- Ice::RouterPrx defaultRouter = communicator()->getDefaultRouter();
- if(!defaultRouter)
- {
- cerr << argv[0] << ": no default router set" << endl;
- return EXIT_FAILURE;
- }
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
- Glacier2::RouterPrx router = Glacier2::RouterPrx::checkedCast(defaultRouter);
{
- if(!router)
+ IceUtil::Mutex::Lock sync(_mutex);
+ Ice::RouterPrx defaultRouter = communicator()->getDefaultRouter();
+ if(!defaultRouter)
+ {
+ cerr << argv[0] << ": no default router set" << endl;
+ return EXIT_FAILURE;
+ }
+
+ _router = Glacier2::RouterPrx::checkedCast(defaultRouter);
+ if(!_router)
{
cerr << argv[0] << ": configured router is not a Glacier2 router" << endl;
return EXIT_FAILURE;
@@ -126,7 +133,7 @@ public:
try
{
- session = ChatSessionPrx::uncheckedCast(router->createSession(id, pw));
+ session = ChatSessionPrx::uncheckedCast(_router->createSession(id, pw));
break;
}
catch(const Glacier2::PermissionDeniedException& ex)
@@ -135,12 +142,15 @@ public:
}
}
- SessionPingThreadPtr ping = new SessionPingThread(session, (long)router->getSessionTimeout() / 2);
- ping->start();
+ {
+ IceUtil::Mutex::Lock sync(_mutex);
+ _ping = new SessionPingThread(session, (long)_router->getSessionTimeout() / 2);
+ _ping->start();
+ }
Ice::Identity callbackReceiverIdent;
callbackReceiverIdent.name = "callbackReceiver";
- callbackReceiverIdent.category = router->getCategoryForClient();
+ callbackReceiverIdent.category = _router->getCategoryForClient();
Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapter("Chat.Client");
ChatCallbackPrx callback = ChatCallbackPrx::uncheckedCast(
@@ -177,9 +187,47 @@ public:
}
while(cin.good());
+ cleanup();
+ }
+ catch(const Ice::Exception& ex)
+ {
+ cerr << ex << endl;
+ cleanup();
+
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+ }
+
+ virtual void
+ interruptCallback(int)
+ {
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+ }
+
+private:
+
+ void
+ cleanup()
+ {
+ IceUtil::Mutex::Lock sync(_mutex);
+ if(_router)
+ {
try
{
- router->destroySession();
+ _router->destroySession();
}
catch(const Ice::ConnectionLostException&)
{
@@ -187,25 +235,16 @@ public:
// Expected: the router closed the connection.
//
}
+ _router = 0;
}
- catch(const Ice::Exception& ex)
+ if(_ping)
{
- cerr << ex << endl;
-
- ping->destroy();
- ping->getThreadControl().join();
-
- return EXIT_FAILURE;
+ _ping->destroy();
+ _ping->getThreadControl().join();
+ _ping = 0;
}
-
- ping->destroy();
- ping->getThreadControl().join();
-
- return EXIT_SUCCESS;
}
-private:
-
void
menu()
{
@@ -223,6 +262,10 @@ private:
}
return s;
}
+
+ IceUtil::Mutex _mutex;
+ Glacier2::RouterPrx _router;
+ SessionPingThreadPtr _ping;
};
int
diff --git a/cpp/demo/Ice/callback/Client.cpp b/cpp/demo/Ice/callback/Client.cpp
index 8a6b237b415..0f40c0371a1 100644
--- a/cpp/demo/Ice/callback/Client.cpp
+++ b/cpp/demo/Ice/callback/Client.cpp
@@ -28,6 +28,7 @@ class CallbackClient : public Ice::Application
public:
virtual int run(int, char*[]);
+ virtual void interruptCallback(int);
private:
@@ -44,6 +45,12 @@ main(int argc, char* argv[])
int
CallbackClient::run(int argc, char* argv[])
{
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
CallbackSenderPrx twoway = CallbackSenderPrx::checkedCast(
communicator()->propertyToProxy("Callback.Client.CallbackServer")->
ice_twoway()->ice_timeout(-1)->ice_secure(false));
@@ -169,6 +176,24 @@ CallbackClient::run(int argc, char* argv[])
}
void
+CallbackClient::interruptCallback(int)
+{
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+}
+
+void
CallbackClient::menu()
{
cout <<
diff --git a/cpp/demo/Ice/converter/Client.cpp b/cpp/demo/Ice/converter/Client.cpp
index 8864838bf69..e833dbc3b48 100644
--- a/cpp/demo/Ice/converter/Client.cpp
+++ b/cpp/demo/Ice/converter/Client.cpp
@@ -113,7 +113,10 @@ main(int argc, char* argv[])
initData.properties->load("config.client");
communicator1 = Ice::initialize(argc, argv, initData);
- communicator2 = Ice::initialize(argc, argv);
+ Ice::InitializationData initData2;
+ initData2.properties = Ice::createProperties();
+ initData2.properties->load("config.client");
+ communicator2 = Ice::initialize(argc, argv, initData2);
status = run(argc, argv, communicator1, communicator2);
}
diff --git a/cpp/demo/Ice/hello/Client.cpp b/cpp/demo/Ice/hello/Client.cpp
index 3aca8c3d934..f2de173ada6 100644
--- a/cpp/demo/Ice/hello/Client.cpp
+++ b/cpp/demo/Ice/hello/Client.cpp
@@ -18,6 +18,7 @@ class HelloClient : public Ice::Application
public:
virtual int run(int, char*[]);
+ virtual void interruptCallback(int);
private:
@@ -34,6 +35,12 @@ main(int argc, char* argv[])
int
HelloClient::run(int argc, char* argv[])
{
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
HelloPrx twoway = HelloPrx::checkedCast(
communicator()->propertyToProxy("Hello.Proxy")->ice_twoway()->ice_timeout(-1)->ice_secure(false));
if(!twoway)
@@ -189,6 +196,24 @@ HelloClient::run(int argc, char* argv[])
}
void
+HelloClient::interruptCallback(int)
+{
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+}
+
+void
HelloClient::menu()
{
cout <<
diff --git a/cpp/demo/Ice/invoke/Client.cpp b/cpp/demo/Ice/invoke/Client.cpp
index 3a687a5e29f..0bfe715f5d1 100644
--- a/cpp/demo/Ice/invoke/Client.cpp
+++ b/cpp/demo/Ice/invoke/Client.cpp
@@ -18,6 +18,7 @@ class InvokeClient : public Ice::Application
public:
virtual int run(int, char*[]);
+ virtual void interruptCallback(int);
private:
@@ -52,6 +53,12 @@ operator<<(ostream& out, Demo::Color c)
int
InvokeClient::run(int argc, char* argv[])
{
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
Ice::ObjectPrx obj = communicator()->propertyToProxy("Printer.Proxy");
menu();
@@ -293,6 +300,24 @@ InvokeClient::run(int argc, char* argv[])
}
void
+InvokeClient::interruptCallback(int)
+{
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+}
+
+void
InvokeClient::menu()
{
cout <<
diff --git a/cpp/demo/Ice/nested/Client.cpp b/cpp/demo/Ice/nested/Client.cpp
index 53d9ae26547..bc10109a1fe 100644
--- a/cpp/demo/Ice/nested/Client.cpp
+++ b/cpp/demo/Ice/nested/Client.cpp
@@ -13,11 +13,13 @@
using namespace std;
using namespace Demo;
+
class NestedClient : public Ice::Application
{
public:
virtual int run(int, char*[]);
+ virtual void interruptCallback(int);
};
int
@@ -30,6 +32,12 @@ main(int argc, char* argv[])
int
NestedClient::run(int argc, char* argv[])
{
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
NestedPrx nested = NestedPrx::checkedCast(communicator()->propertyToProxy("Nested.Client.NestedServer"));
if(!nested)
{
@@ -70,3 +78,27 @@ NestedClient::run(int argc, char* argv[])
return EXIT_SUCCESS;
}
+
+void
+NestedClient::interruptCallback(int)
+{
+/*
+ * For this demo we won't destroy the communicator since it has to
+ * wait for any outstanding invocations to complete which may take
+ * some time if the nesting level is exceeded.
+ *
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+*/
+ exit(EXIT_SUCCESS);
+}
diff --git a/cpp/demo/Ice/session/Client.cpp b/cpp/demo/Ice/session/Client.cpp
index fc78b4dee0c..e0be25f7d61 100755
--- a/cpp/demo/Ice/session/Client.cpp
+++ b/cpp/demo/Ice/session/Client.cpp
@@ -72,10 +72,20 @@ class SessionClient : public Ice::Application
public:
virtual int run(int, char*[]);
+ virtual void interruptCallback(int);
private:
void menu();
+ void cleanup(bool);
+
+ //
+ // The interrupt callback and main can run concurrently with one
+ // another so shared variables must be mutex protected.
+ //
+ IceUtil::Mutex _mutex;
+ SessionRefreshThreadPtr _refresh;
+ SessionPrx _session;
};
int
@@ -88,6 +98,12 @@ main(int argc, char* argv[])
int
SessionClient::run(int argc, char* argv[])
{
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
string name;
cout << "Please enter your name ==> ";
cin >> name;
@@ -104,11 +120,14 @@ SessionClient::run(int argc, char* argv[])
return EXIT_FAILURE;
}
- SessionPrx session = factory->create(name);
-
- SessionRefreshThreadPtr refresh = new SessionRefreshThread(
- communicator()->getLogger(), IceUtil::Time::seconds(5), session);
- refresh->start();
+ {
+ IceUtil::Mutex::Lock sync(_mutex);
+ _session = factory->create(name);
+
+ _refresh = new SessionRefreshThread(
+ communicator()->getLogger(), IceUtil::Time::seconds(5), _session);
+ _refresh->start();
+ }
vector<HelloPrx> hellos;
@@ -144,7 +163,7 @@ SessionClient::run(int argc, char* argv[])
}
else if(c == 'c')
{
- hellos.push_back(session->createHello());
+ hellos.push_back(_session->createHello());
cout << "Created hello object " << hellos.size() - 1 << endl;
}
else if(c == 's')
@@ -179,14 +198,7 @@ SessionClient::run(int argc, char* argv[])
// is set to 0 so that if session->destroy() raises an exception
// the thread will not be re-terminated and re-joined.
//
- refresh->terminate();
- refresh->getThreadControl().join();
- refresh = 0;
-
- if(destroy)
- {
- session->destroy();
- }
+ cleanup(destroy);
if(shutdown)
{
factory->shutdown();
@@ -194,14 +206,12 @@ SessionClient::run(int argc, char* argv[])
}
catch(...)
{
- //
- // The refresher thread must be terminated in the event of a
- // failure.
- //
- if(refresh)
+ try
+ {
+ cleanup(true);
+ }
+ catch(...)
{
- refresh->terminate();
- refresh->getThreadControl().join();
}
throw;
}
@@ -210,6 +220,50 @@ SessionClient::run(int argc, char* argv[])
}
void
+SessionClient::interruptCallback(int)
+{
+ //
+ // Terminate the refresh thread, destroy the session and then
+ // destroy the communicator, followed by an exit. We have to call
+ // exit because main may be blocked in a cin >> s call which
+ // cannot be interrupted portably.
+ //
+ cleanup(true);
+
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+}
+
+void
+SessionClient::cleanup(bool destroy)
+{
+ IceUtil::Mutex::Lock sync(_mutex);
+ if(_refresh)
+ {
+ _refresh->terminate();
+ _refresh->getThreadControl().join();
+ _refresh = 0;
+ }
+
+ if(destroy && _session)
+ {
+ _session->destroy();
+ _session = 0;
+ }
+}
+
+void
SessionClient::menu()
{
cout <<
diff --git a/cpp/demo/Ice/throughput/Client.cpp b/cpp/demo/Ice/throughput/Client.cpp
index 03bfd13aeec..a2c00c008a3 100644
--- a/cpp/demo/Ice/throughput/Client.cpp
+++ b/cpp/demo/Ice/throughput/Client.cpp
@@ -20,6 +20,7 @@ class ThroughputClient : public Ice::Application
public:
virtual int run(int, char*[]);
+ virtual void interruptCallback(int);
private:
@@ -36,6 +37,12 @@ main(int argc, char* argv[])
int
ThroughputClient::run(int argc, char* argv[])
{
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
Ice::ObjectPrx base = communicator()->propertyToProxy("Throughput.Throughput");
ThroughputPrx throughput = ThroughputPrx::checkedCast(base);
if(!throughput)
@@ -378,6 +385,24 @@ ThroughputClient::run(int argc, char* argv[])
}
void
+ThroughputClient::interruptCallback(int)
+{
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+}
+
+void
ThroughputClient::menu()
{
cout <<
diff --git a/cpp/demo/Ice/value/Client.cpp b/cpp/demo/Ice/value/Client.cpp
index a375da519de..de4885f7f79 100644
--- a/cpp/demo/Ice/value/Client.cpp
+++ b/cpp/demo/Ice/value/Client.cpp
@@ -19,6 +19,7 @@ class ValueClient : public Ice::Application
public:
virtual int run(int, char*[]);
+ virtual void interruptCallback(int);
};
int
@@ -31,6 +32,12 @@ main(int argc, char* argv[])
int
ValueClient::run(int argc, char* argv[])
{
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
Ice::ObjectPrx base = communicator()->propertyToProxy("Value.Initial");
InitialPrx initial = InitialPrx::checkedCast(base);
if(!initial)
@@ -174,3 +181,21 @@ ValueClient::run(int argc, char* argv[])
return EXIT_SUCCESS;
}
+
+void
+ValueClient::interruptCallback(int)
+{
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+}
diff --git a/cpp/demo/IceBox/hello/Client.cpp b/cpp/demo/IceBox/hello/Client.cpp
index 17764a6a845..830f24aa7ef 100644
--- a/cpp/demo/IceBox/hello/Client.cpp
+++ b/cpp/demo/IceBox/hello/Client.cpp
@@ -18,6 +18,7 @@ class HelloClient : public Ice::Application
public:
virtual int run(int, char*[]);
+ virtual void interruptCallback(int);
private:
@@ -50,6 +51,12 @@ HelloClient::menu()
int
HelloClient::run(int argc, char* argv[])
{
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
HelloPrx twoway = HelloPrx::checkedCast(
communicator()->propertyToProxy("Hello.Proxy")->ice_twoway()->ice_timeout(-1)->ice_secure(false));
if(!twoway)
@@ -153,3 +160,21 @@ HelloClient::run(int argc, char* argv[])
return EXIT_SUCCESS;
}
+
+void
+HelloClient::interruptCallback(int)
+{
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+}
diff --git a/cpp/demo/IceGrid/allocate/Client.cpp b/cpp/demo/IceGrid/allocate/Client.cpp
index b4df84f00c9..79b21842dfd 100644
--- a/cpp/demo/IceGrid/allocate/Client.cpp
+++ b/cpp/demo/IceGrid/allocate/Client.cpp
@@ -57,7 +57,7 @@ public:
private:
- IceGrid::SessionPrx _session;
+ const IceGrid::SessionPrx _session;
const IceUtil::Time _timeout;
bool _destroy;
};
@@ -69,11 +69,17 @@ class HelloClient : public Ice::Application
public:
virtual int run(int, char*[]);
+ virtual void interruptCallback(int);
private:
+ void cleanup();
void menu();
string trim(const string&);
+
+ IceUtil::Mutex _mutex;
+ IceGrid::SessionPrx _session;
+ SessionKeepAliveThreadPtr _keepAlive;
};
int
@@ -83,43 +89,25 @@ main(int argc, char* argv[])
return app.main(argc, argv, "config.client");
}
-void
-HelloClient::menu()
-{
- cout <<
- "usage:\n"
- "t: send greeting\n"
- "s: shutdown server\n"
- "x: exit\n"
- "?: help\n";
-}
-
-string
-HelloClient::trim(const string& s)
-{
- static const string delims = "\t\r\n ";
- string::size_type last = s.find_last_not_of(delims);
- if(last != string::npos)
- {
- return s.substr(s.find_first_not_of(delims), last+1);
- }
- return s;
-}
-
int
HelloClient::run(int argc, char* argv[])
{
int status = EXIT_SUCCESS;
- IceGrid::RegistryPrx registry =
- IceGrid::RegistryPrx::checkedCast(communicator()->stringToProxy("DemoIceGrid/Registry"));
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
+ IceGrid::RegistryPrx registry = IceGrid::RegistryPrx::checkedCast(
+ communicator()->stringToProxy("DemoIceGrid/Registry"));
if(!registry)
{
cerr << argv[0] << ": could not contact registry" << endl;
return EXIT_FAILURE;
}
- IceGrid::SessionPrx session;
while(true)
{
cout << "This demo accepts any user-id / password combination.\n";
@@ -136,7 +124,8 @@ HelloClient::run(int argc, char* argv[])
try
{
- session = registry->createSession(id, password);
+ IceUtil::Mutex::Lock sync(_mutex);
+ _session = registry->createSession(id, password);
break;
}
catch(const IceGrid::PermissionDeniedException& ex)
@@ -145,8 +134,11 @@ HelloClient::run(int argc, char* argv[])
}
}
- SessionKeepAliveThreadPtr keepAlive = new SessionKeepAliveThread(session, registry->getSessionTimeout() / 2);
- keepAlive->start();
+ {
+ IceUtil::Mutex::Lock sync(_mutex);
+ _keepAlive = new SessionKeepAliveThread(_session, registry->getSessionTimeout() / 2);
+ _keepAlive->start();
+ }
try
{
@@ -159,11 +151,11 @@ HelloClient::run(int argc, char* argv[])
HelloPrx hello;
try
{
- hello = HelloPrx::checkedCast(session->allocateObjectById(communicator()->stringToIdentity("hello")));
+ hello = HelloPrx::checkedCast(_session->allocateObjectById(communicator()->stringToIdentity("hello")));
}
catch(const IceGrid::ObjectNotRegisteredException&)
{
- hello = HelloPrx::checkedCast(session->allocateObjectByType("::Demo::Hello"));
+ hello = HelloPrx::checkedCast(_session->allocateObjectByType("::Demo::Hello"));
}
menu();
@@ -215,14 +207,71 @@ HelloClient::run(int argc, char* argv[])
status = EXIT_FAILURE;
}
+ cleanup();
+ return status;
+}
+
+void
+HelloClient::interruptCallback(int)
+{
+ cleanup();
+
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+}
+
+void
+HelloClient::cleanup()
+{
+ IceUtil::Mutex::Lock sync(_mutex);
//
// Destroy the keepAlive thread and the sesion object otherwise
// the session will be kept allocated until the timeout occurs.
// Destroying the session will release all allocated objects.
//
- keepAlive->destroy();
- keepAlive->getThreadControl().join();
- session->destroy();
+ if(_keepAlive)
+ {
+ _keepAlive->destroy();
+ _keepAlive->getThreadControl().join();
+ _keepAlive = 0;
+ }
+ if(_session)
+ {
+ _session->destroy();
+ _session = 0;
+ }
+}
- return status;
+void
+HelloClient::menu()
+{
+ cout <<
+ "usage:\n"
+ "t: send greeting\n"
+ "s: shutdown server\n"
+ "x: exit\n"
+ "?: help\n";
+}
+
+string
+HelloClient::trim(const string& s)
+{
+ static const string delims = "\t\r\n ";
+ string::size_type last = s.find_last_not_of(delims);
+ if(last != string::npos)
+ {
+ return s.substr(s.find_first_not_of(delims), last+1);
+ }
+ return s;
}
diff --git a/cpp/demo/IceGrid/sessionActivation/Client.cpp b/cpp/demo/IceGrid/sessionActivation/Client.cpp
index d8fc48e65dc..b4e9f719f53 100644
--- a/cpp/demo/IceGrid/sessionActivation/Client.cpp
+++ b/cpp/demo/IceGrid/sessionActivation/Client.cpp
@@ -69,11 +69,17 @@ class HelloClient : public Ice::Application
public:
virtual int run(int, char*[]);
+ virtual void interruptCallback(int);
private:
+ void cleanup();
void menu();
string trim(const string&);
+
+ IceUtil::Mutex _mutex;
+ IceGrid::SessionPrx _session;
+ SessionKeepAliveThreadPtr _keepAlive;
};
int
@@ -83,32 +89,17 @@ main(int argc, char* argv[])
return app.main(argc, argv, "config.client");
}
-void
-HelloClient::menu()
-{
- cout <<
- "usage:\n"
- "t: send greeting\n"
- "x: exit\n"
- "?: help\n";
-}
-
-string
-HelloClient::trim(const string& s)
-{
- static const string delims = "\t\r\n ";
- string::size_type last = s.find_last_not_of(delims);
- if(last != string::npos)
- {
- return s.substr(s.find_first_not_of(delims), last+1);
- }
- return s;
-}
-
int
HelloClient::run(int argc, char* argv[])
{
int status = EXIT_SUCCESS;
+
+ //
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
IceGrid::RegistryPrx registry =
IceGrid::RegistryPrx::checkedCast(communicator()->stringToProxy("DemoIceGrid/Registry"));
if(!registry)
@@ -117,7 +108,6 @@ HelloClient::run(int argc, char* argv[])
return EXIT_FAILURE;
}
- IceGrid::SessionPrx session;
while(true)
{
cout << "This demo accepts any user-id / password combination.\n";
@@ -134,7 +124,8 @@ HelloClient::run(int argc, char* argv[])
try
{
- session = registry->createSession(id, password);
+ IceUtil::Mutex::Lock sync(_mutex);
+ _session = registry->createSession(id, password);
break;
}
catch(const IceGrid::PermissionDeniedException& ex)
@@ -143,12 +134,15 @@ HelloClient::run(int argc, char* argv[])
}
}
- SessionKeepAliveThreadPtr keepAlive = new SessionKeepAliveThread(session, registry->getSessionTimeout() / 2);
- keepAlive->start();
+ {
+ IceUtil::Mutex::Lock sync(_mutex);
+ _keepAlive = new SessionKeepAliveThread(_session, registry->getSessionTimeout() / 2);
+ _keepAlive->start();
+ }
try
{
- HelloPrx hello = HelloPrx::checkedCast(session->allocateObjectById(communicator()->stringToIdentity("hello")));
+ HelloPrx hello = HelloPrx::checkedCast(_session->allocateObjectById(communicator()->stringToIdentity("hello")));
menu();
@@ -205,15 +199,72 @@ HelloClient::run(int argc, char* argv[])
status = EXIT_FAILURE;
}
+ cleanup();
+
+ return status;
+}
+
+void
+HelloClient::interruptCallback(int)
+{
+ cleanup();
+
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+}
+
+void
+HelloClient::cleanup()
+{
+ IceUtil::Mutex::Lock sync(_mutex);
//
// Destroy the keepAlive thread and the sesion object otherwise
// the session will be kept allocated until the timeout occurs.
// Destroying the session will release all allocated objects.
//
- keepAlive->destroy();
- keepAlive->getThreadControl().join();
- session->destroy();
+ if(_keepAlive)
+ {
+ _keepAlive->destroy();
+ _keepAlive->getThreadControl().join();
+ _keepAlive = 0;
+ }
+ if(_session)
+ {
+ _session->destroy();
+ _session = 0;
+ }
+}
- return status;
+void
+HelloClient::menu()
+{
+ cout <<
+ "usage:\n"
+ "t: send greeting\n"
+ "x: exit\n"
+ "?: help\n";
+}
+
+string
+HelloClient::trim(const string& s)
+{
+ static const string delims = "\t\r\n ";
+ string::size_type last = s.find_last_not_of(delims);
+ if(last != string::npos)
+ {
+ return s.substr(s.find_first_not_of(delims), last+1);
+ }
+ return s;
}
diff --git a/cpp/demo/IceGrid/simple/Client.cpp b/cpp/demo/IceGrid/simple/Client.cpp
index 13259587dfb..bf86e3ee294 100644
--- a/cpp/demo/IceGrid/simple/Client.cpp
+++ b/cpp/demo/IceGrid/simple/Client.cpp
@@ -19,6 +19,7 @@ class HelloClient : public Ice::Application
public:
virtual int run(int, char*[]);
+ virtual void interruptCallback(int);
private:
@@ -47,6 +48,12 @@ int
HelloClient::run(int argc, char* argv[])
{
//
+ // Since this is an interactive demo we want the custom interrupt
+ // callback to be called when the process is interrupted.
+ //
+ userCallbackOnInterrupt();
+
+ //
// First we try to connect to the object with the `hello'
// identity. If it's not registered with the registry, we
// search for an object with the ::Demo::Hello type.
@@ -108,3 +115,20 @@ HelloClient::run(int argc, char* argv[])
return EXIT_SUCCESS;
}
+void
+HelloClient::interruptCallback(int)
+{
+ try
+ {
+ communicator()->destroy();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << appName() << ": " << ex << endl;
+ }
+ catch(...)
+ {
+ cerr << appName() << ": unknown exception" << endl;
+ }
+ exit(EXIT_SUCCESS);
+}
diff --git a/cpp/include/Ice/Application.h b/cpp/include/Ice/Application.h
index ca3cd658188..4f2c27300e0 100644
--- a/cpp/include/Ice/Application.h
+++ b/cpp/include/Ice/Application.h
@@ -38,6 +38,16 @@ public:
virtual int run(int, char*[]) = 0;
//
+ // Override this to provide a custom application interrupt
+ // hook. You must call userCallbackOnInterrupt for this method to
+ // be called. Note that the interruptCallback can be called
+ // concurrently with any other thread (including main) in your
+ // application and thus must take appropriate concurrency
+ // precautions.
+ //
+ virtual void interruptCallback(int);
+
+ //
// Return the application name, i.e., argv[0].
//
static const char* appName();
@@ -58,6 +68,7 @@ public:
static void destroyOnInterrupt();
static void shutdownOnInterrupt();
static void ignoreInterrupt();
+ static void userCallbackOnInterrupt();
//
// These methods can be used to temporarily block a signal and
@@ -81,7 +92,6 @@ public:
//
static bool interrupted();
-
#if defined(__SUNPRO_CC)
//
// Sun C++ 5.x does not like classes with no data members
diff --git a/cpp/src/Ice/Application.cpp b/cpp/src/Ice/Application.cpp
index 8bee23ebe60..dfc03f6949c 100644
--- a/cpp/src/Ice/Application.cpp
+++ b/cpp/src/Ice/Application.cpp
@@ -40,6 +40,7 @@ static CtrlCHandlerCallback _previousCallback = 0;
// only the main thread and CtrlCHandler threads are running.
//
static const char* _appName = 0;
+static Application* _application;
static CommunicatorPtr _communicator;
static CtrlCHandler* _ctrlCHandler = 0;
static bool _nohup = false;
@@ -62,7 +63,8 @@ const DWORD SIGHUP = CTRL_LOGOFF_EVENT;
// CtrlCHandler callbacks.
//
-static void holdInterruptCallback(int signal)
+static void
+holdInterruptCallback(int signal)
{
CtrlCHandlerCallback callback = 0;
{
@@ -89,7 +91,8 @@ static void holdInterruptCallback(int signal)
}
}
-static void destroyOnInterruptCallback(int signal)
+static void
+destroyOnInterruptCallback(int signal)
{
{
StaticMutex::Lock lock(_mutex);
@@ -151,7 +154,8 @@ static void destroyOnInterruptCallback(int signal)
}
-static void shutdownOnInterruptCallback(int signal)
+static void
+shutdownOnInterruptCallback(int signal)
{
{
StaticMutex::Lock lock(_mutex);
@@ -171,6 +175,7 @@ static void shutdownOnInterruptCallback(int signal)
_interrupted = true;
}
+ assert(_communicator != 0);
try
{
_communicator->shutdown();
@@ -209,6 +214,65 @@ static void shutdownOnInterruptCallback(int signal)
}
+static void
+userCallbackOnInterruptCallback(int signal)
+{
+ {
+ StaticMutex::Lock lock(_mutex);
+ if(_destroyed)
+ {
+ //
+ // Being destroyed by main thread
+ //
+ return;
+ }
+ if(_nohup && signal == SIGHUP)
+ {
+ return;
+ }
+ assert(!_callbackInProgress);
+ _callbackInProgress = true;
+ _interrupted = true;
+ }
+
+ assert(_application != 0);
+ try
+ {
+ _application->interruptCallback(signal);
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << _appName << " (while interrupting in response to signal " << signal
+ << "): " << ex << endl;
+ }
+ catch(const std::exception& ex)
+ {
+ cerr << _appName << " (while interrupting in response to signal " << signal
+ << "): std::exception: " << ex.what() << endl;
+ }
+ catch(const std::string& msg)
+ {
+ cerr << _appName << " (while interrupting in response to signal " << signal
+ << "): " << msg << endl;
+ }
+ catch(const char * msg)
+ {
+ cerr << _appName << " (while interrupting in response to signal " << signal
+ << "): " << msg << endl;
+ }
+ catch(...)
+ {
+ cerr << _appName << " (while interrupting in response to signal " << signal
+ << "): unknown exception" << endl;
+ }
+
+ {
+ StaticMutex::Lock lock(_mutex);
+ _callbackInProgress = false;
+ }
+ _condVar->signal();
+}
+
Ice::Application::Application()
{
@@ -319,6 +383,7 @@ Ice::Application::main(int argc, char* argv[], const InitializationData& initDat
_interrupted = false;
_appName = argv[0];
+ _application = this;
_communicator = initialize(argc, argv, initData);
_destroyed = false;
@@ -327,7 +392,6 @@ Ice::Application::main(int argc, char* argv[], const InitializationData& initDat
//
_nohup = (_communicator->getProperties()->getPropertyAsInt("Ice.Nohup") > 0);
-
//
// The default is to destroy when a signal is received.
//
@@ -361,8 +425,9 @@ Ice::Application::main(int argc, char* argv[], const InitializationData& initDat
}
//
- // Don't want any new interrupt
- // And at this point (post-run), it would not make sense to release a held signal to run shutdown or destroy.
+ // Don't want any new interrupt and at this point (post-run),
+ // it would not make sense to release a held signal to run
+ // shutdown or destroy.
//
ignoreInterrupt();
@@ -380,10 +445,12 @@ Ice::Application::main(int argc, char* argv[], const InitializationData& initDat
{
_destroyed = true;
//
- // And _communicator != 0, meaning will be destroyed next,
- // _destroyed = true also ensures that any remaining callback won't do anything
+ // And _communicator != 0, meaning will be destroyed
+ // next, _destroyed = true also ensures that any
+ // remaining callback won't do anything
//
}
+ _application = 0;
}
if(_communicator != 0)
@@ -424,6 +491,11 @@ Ice::Application::main(int argc, char* argv[], const InitializationData& initDat
return status;
}
+void
+Ice::Application::interruptCallback(int)
+{
+}
+
const char*
Ice::Application::appName()
{
@@ -438,11 +510,10 @@ Ice::Application::communicator()
void
Ice::Application::destroyOnInterrupt()
-{
+{
//
// if _ctrlCHandler == 0, it's really a bug in the caller
//
-
if(_ctrlCHandler != 0)
{
StaticMutex::Lock lock(_mutex); // we serialize all the interrupt-setting
@@ -498,6 +569,25 @@ Ice::Application::ignoreInterrupt()
}
void
+Ice::Application::userCallbackOnInterrupt()
+{
+ if(_ctrlCHandler != 0)
+ {
+ StaticMutex::Lock lock(_mutex); // we serialize all the interrupt-setting
+ if(_ctrlCHandler->getCallback() == holdInterruptCallback)
+ {
+ _released = true;
+ _ctrlCHandler->setCallback(userCallbackOnInterruptCallback);
+ _condVar->signal();
+ }
+ else
+ {
+ _ctrlCHandler->setCallback(userCallbackOnInterruptCallback);
+ }
+ }
+}
+
+void
Ice::Application::holdInterrupt()
{
if(_ctrlCHandler != 0)