summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorBernard Normier <bernard@zeroc.com>2003-04-18 21:44:09 +0000
committerBernard Normier <bernard@zeroc.com>2003-04-18 21:44:09 +0000
commitab818e033a7c29898da7778a75bd69a2bcf530c5 (patch)
tree9f15cdc381f1c3cdbdd327120c43060d55b9ee16 /cpp/src
parentbug fix for service shutdown (diff)
downloadice-ab818e033a7c29898da7778a75bd69a2bcf530c5.tar.bz2
ice-ab818e033a7c29898da7778a75bd69a2bcf530c5.tar.xz
ice-ab818e033a7c29898da7778a75bd69a2bcf530c5.zip
StaticMutex, CtrlCHandler and Applicaton signal handling update
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Freeze/Application.cpp1
-rw-r--r--cpp/src/Ice/Application.cpp303
-rw-r--r--cpp/src/Ice/CommunicatorI.cpp19
-rw-r--r--cpp/src/Ice/CommunicatorI.h11
-rw-r--r--cpp/src/Ice/ThreadPool.h2
-rw-r--r--cpp/src/IceUtil/.depend4
-rw-r--r--cpp/src/IceUtil/CtrlCHandler.cpp208
-rw-r--r--cpp/src/IceUtil/Makefile2
-rw-r--r--cpp/src/IceUtil/StaticMutex.cpp79
-rw-r--r--cpp/src/IceUtil/iceutil.dsp16
10 files changed, 466 insertions, 179 deletions
diff --git a/cpp/src/Freeze/Application.cpp b/cpp/src/Freeze/Application.cpp
index 9b40cb5f3c4..ecd80f0e3b2 100644
--- a/cpp/src/Freeze/Application.cpp
+++ b/cpp/src/Freeze/Application.cpp
@@ -81,6 +81,5 @@ Freeze::Application::run(int argc, char* argv[])
dbEnv = 0;
}
- defaultInterrupt();
return status;
}
diff --git a/cpp/src/Ice/Application.cpp b/cpp/src/Ice/Application.cpp
index 943514b6f16..b0d0268ceb8 100644
--- a/cpp/src/Ice/Application.cpp
+++ b/cpp/src/Ice/Application.cpp
@@ -13,33 +13,102 @@
// **********************************************************************
#include <Ice/Application.h>
-
-#ifndef _WIN32
-#include <signal.h>
-#endif
+#include <IceUtil/StaticMutex.h>
+#include <IceUtil/CtrlCHandler.h>
+#include <IceUtil/Cond.h>
+#include <memory>
using namespace std;
using namespace Ice;
+using namespace IceUtil;
-const char* Application::_appName = 0;
-CommunicatorPtr Application::_communicator;
+static const char* _appName = 0;
+static CommunicatorPtr _communicator;
-bool Application::_interrupted = false;
+static bool _interrupted = false;
+static StaticMutex _mutex = ICE_STATIC_MUTEX_INITIALIZER;
-#ifndef _WIN32
-const int Application::signals[] = { SIGHUP, SIGINT, SIGTERM };
-sigset_t Application::signalSet;
+static bool _released = false;
+static auto_ptr<Cond> _condVar;
+static auto_ptr<IceUtil::CtrlCHandler> _ctrlCHandler;
+static IceUtil::CtrlCHandlerCallback _previousCallback = 0;
+static bool _nohup = false;
+
+#ifdef _WIN32
+const DWORD SIGHUP = CTRL_LOGOFF_EVENT;
+#else
+# include <csignal>
#endif
-Ice::Application::Application()
+
+// CtrlCHandler callbacks
+//
+
+static void holdInterruptCallback(int signal)
{
-#ifndef _WIN32
- sigemptyset(&signalSet);
- for (unsigned i = 0; i < sizeof(signals) / sizeof(*signals); ++i)
{
- sigaddset(&signalSet, signals[i]);
+ StaticMutex::Lock lock(_mutex);
+ while(!_released)
+ {
+ _condVar->wait(lock);
+ }
}
-#endif
+
+ // Use the current callback to process this (old) signal
+ //
+ CtrlCHandlerCallback callback = _ctrlCHandler->getCallback();
+ if(callback != 0)
+ {
+ callback(signal);
+ }
+}
+
+static void shutdownOnInterruptCallback(int signal)
+{
+ if(_nohup && signal == SIGHUP)
+ {
+ return;
+ }
+
+ {
+ StaticMutex::Lock lock(_mutex);
+ _interrupted = true;
+ }
+
+ try
+ {
+ _communicator->shutdown();
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << _appName << " (while shutting down in response to signal " << signal
+ << "): " << ex << endl;
+ }
+ catch(const std::exception& ex)
+ {
+ cerr << _appName << " (while shutting down in response to signal " << signal
+ << "): std::exception: " << ex.what() << endl;
+ }
+ catch(const std::string& msg)
+ {
+ cerr << _appName << " (while shutting down in response to signal " << signal
+ << "): " << msg << endl;
+ }
+ catch(const char * msg)
+ {
+ cerr << _appName << " (while shutting down in response to signal " << signal
+ << "): " << msg << endl;
+ }
+ catch(...)
+ {
+ cerr << _appName << " (while shutting down in response to signal " << signal
+ << "): unknown exception" << endl;
+ }
+}
+
+
+Ice::Application::Application()
+{
}
Ice::Application::~Application()
@@ -55,8 +124,17 @@ Ice::Application::main(int argc, char* argv[], const char* configFile)
return EXIT_FAILURE;
}
- Application::_interrupted = false;
+ _interrupted = false;
_appName = argv[0];
+ if(_condVar.get() == 0)
+ {
+ _condVar.reset(new Cond);
+ }
+
+
+ // Ignore signals for a little while
+ //
+ _ctrlCHandler.reset(new IceUtil::CtrlCHandler);
int status;
@@ -72,6 +150,15 @@ Ice::Application::main(int argc, char* argv[], const char* configFile)
{
_communicator = initialize(argc, argv);
}
+
+ // Used by shutdownOnInterruptCallback
+ //
+ _nohup = (_communicator->getProperties()->getPropertyAsInt("Ice.Nohup") > 0);
+
+ // The default is to shutdown when a signal is received:
+ //
+ shutdownOnInterrupt();
+
status = run(argc, argv);
}
catch(const Exception& ex)
@@ -102,6 +189,11 @@ Ice::Application::main(int argc, char* argv[], const char* configFile)
if(_communicator)
{
+ // We don't want to handle signals anymore
+ //
+ ignoreInterrupt(); // will release any signal still held
+ _ctrlCHandler.reset();
+
try
{
_communicator->destroy();
@@ -149,164 +241,83 @@ Ice::Application::communicator()
return _communicator;
}
-#ifdef _WIN32
-
-BOOL WINAPI
-Ice::interruptHandler(DWORD)
-{
- Application::_interrupted = true;
-
- //
- // Don't use Application::communicator(), this is not signal-safe.
- //
- assert(Application::_communicator);
- Application::_communicator->signalShutdown();
- return TRUE;
-}
-
-enum InterruptDisposition { Shutdown, Ignore, Default };
-static InterruptDisposition currentDisposition = Default;
-
void
Ice::Application::shutdownOnInterrupt()
{
- SetConsoleCtrlHandler(NULL, FALSE);
- SetConsoleCtrlHandler(interruptHandler, TRUE);
- currentDisposition = Shutdown;
-}
-
-void
-Ice::Application::ignoreInterrupt()
-{
- SetConsoleCtrlHandler(interruptHandler, FALSE);
- SetConsoleCtrlHandler(NULL, TRUE);
- currentDisposition = Ignore;
-}
-
-void
-Ice::Application::defaultInterrupt()
-{
- SetConsoleCtrlHandler(interruptHandler, FALSE);
- SetConsoleCtrlHandler(NULL, FALSE);
- currentDisposition = Default;
-}
-
-void
-Ice::Application::holdInterrupt()
-{
- //
- // With Windows, we can't block signals and
- // remember them the way we can with UNIX,
- // so "holding" an interrupt is the same as
- // ignoring it.
- //
- SetConsoleCtrlHandler(interruptHandler, FALSE);
- SetConsoleCtrlHandler(NULL, TRUE);
-}
-
-void
-Ice::Application::releaseInterrupt()
-{
- //
- // Restore current signal disposition.
- //
- switch(currentDisposition)
+ assert(_ctrlCHandler.get() != 0);
+
+ StaticMutex::Lock lock(_mutex);
+ if(_ctrlCHandler->getCallback() == holdInterruptCallback)
{
- case Shutdown:
- {
- shutdownOnInterrupt();
- break;
- }
- case Ignore:
- {
- ignoreInterrupt();
- break;
- }
- case Default:
- {
- defaultInterrupt();
- break;
- }
- default:
- {
- assert(false);
- break;
- }
+ _released = true;
+ _ctrlCHandler->setCallback(shutdownOnInterruptCallback);
+ lock.release();
+ _condVar->signal();
}
-}
-
-#else
-
-void
-Ice::interruptHandler(int)
-{
- Application::_interrupted = true;
-
- //
- // Don't use Application::communicator(), this is not signal-safe.
- //
- assert(Application::_communicator);
- Application::_communicator->signalShutdown();
-}
-
-void
-Ice::Application::shutdownOnInterrupt()
-{
- struct sigaction action;
- memset(&action, 0, sizeof(action));
- action.sa_handler = interruptHandler;
- action.sa_mask = signalSet;
- action.sa_flags = SA_RESTART;
- for (unsigned i = 0; i < sizeof(signals) / sizeof(*signals); ++i)
+ else
{
- sigaction(signals[i], &action, 0);
+ _ctrlCHandler->setCallback(shutdownOnInterruptCallback);
}
}
void
Ice::Application::ignoreInterrupt()
{
- struct sigaction action;
- memset(&action, 0, sizeof(action));
- action.sa_handler = SIG_IGN;
- action.sa_mask = signalSet;
- action.sa_flags = SA_RESTART;
- for (unsigned i = 0; i < sizeof(signals) / sizeof(*signals); ++i)
+ assert(_ctrlCHandler.get() != 0);
+
+ StaticMutex::Lock lock(_mutex);
+ if(_ctrlCHandler->getCallback() == holdInterruptCallback)
{
- sigaction(signals[i], &action, 0);
+ _released = true;
+ _ctrlCHandler->setCallback(0);
+ lock.release();
+ _condVar->signal();
}
-}
-
-void
-Ice::Application::defaultInterrupt()
-{
- struct sigaction action;
- memset(&action, 0, sizeof(action));
- action.sa_handler = SIG_DFL;
- action.sa_mask = signalSet;
- action.sa_flags = SA_RESTART;
- for (unsigned i = 0; i < sizeof(signals) / sizeof(*signals); ++i)
+ else
{
- sigaction(signals[i], &action, 0);
+ _ctrlCHandler->setCallback(0);
}
}
void
Ice::Application::holdInterrupt()
{
- sigprocmask(SIG_BLOCK, &signalSet, 0);
+ assert(_ctrlCHandler.get() != 0);
+
+ StaticMutex::Lock lock(_mutex);
+ if(_ctrlCHandler->getCallback() != holdInterruptCallback)
+ {
+ _previousCallback = _ctrlCHandler->getCallback();
+ _released = false;
+ _ctrlCHandler->setCallback(holdInterruptCallback);
+ }
+ // else, we were already holding signals
}
void
Ice::Application::releaseInterrupt()
{
- sigprocmask(SIG_UNBLOCK, &signalSet, 0);
-}
+ assert(_ctrlCHandler.get() != 0);
-#endif
+ StaticMutex::Lock lock(_mutex);
+ if(_ctrlCHandler->getCallback() == holdInterruptCallback)
+ {
+ // Note that it's very possible no signal is held;
+ // in this case the callback is just replaced and
+ // setting _released to true and signalling _condVar
+ // do no harm.
+
+ _released = true;
+ _ctrlCHandler->setCallback(_previousCallback);
+ lock.release();
+ _condVar->signal();
+ }
+ // else nothing to release
+}
bool
Ice::Application::interrupted()
{
- return Application::_interrupted;
+ StaticMutex::Lock lock(_mutex);
+ return _interrupted;
}
diff --git a/cpp/src/Ice/CommunicatorI.cpp b/cpp/src/Ice/CommunicatorI.cpp
index e9a2ad4fcc6..f0272f655ca 100644
--- a/cpp/src/Ice/CommunicatorI.cpp
+++ b/cpp/src/Ice/CommunicatorI.cpp
@@ -17,7 +17,6 @@
#include <Ice/Properties.h>
#include <Ice/ReferenceFactory.h>
#include <Ice/ProxyFactory.h>
-#include <Ice/ThreadPool.h>
#include <Ice/ObjectFactoryManager.h>
#include <Ice/UserExceptionFactoryManager.h>
#include <Ice/ObjectAdapterFactory.h>
@@ -40,7 +39,6 @@ Ice::CommunicatorI::destroy()
if(!_destroyed) // Don't destroy twice.
{
_destroyed = true;
- _serverThreadPool = 0;
instance = _instance;
}
}
@@ -74,18 +72,6 @@ Ice::CommunicatorI::shutdown()
}
void
-Ice::CommunicatorI::signalShutdown()
-{
- //
- // No mutex locking here! This operation must be signal-safe.
- //
- if(_serverThreadPool)
- {
- _serverThreadPool->initiateShutdown();
- }
-}
-
-void
Ice::CommunicatorI::waitForShutdown()
{
ObjectAdapterFactoryPtr objectAdapterFactory;
@@ -140,11 +126,6 @@ Ice::CommunicatorI::createObjectAdapter(const string& name)
ObjectAdapterPtr adapter = _instance->objectAdapterFactory()->createObjectAdapter(name);
- if(!_serverThreadPool) // Lazy initialization of _serverThreadPool.
- {
- _serverThreadPool = _instance->serverThreadPool();
- }
-
return adapter;
}
diff --git a/cpp/src/Ice/CommunicatorI.h b/cpp/src/Ice/CommunicatorI.h
index d4b7d89a013..6b6f35bfa55 100644
--- a/cpp/src/Ice/CommunicatorI.h
+++ b/cpp/src/Ice/CommunicatorI.h
@@ -17,7 +17,6 @@
#include <IceUtil/RecMutex.h>
-#include <Ice/ThreadPoolF.h>
#include <Ice/DynamicLibraryF.h>
#include <Ice/Initialize.h>
#include <Ice/Communicator.h>
@@ -31,7 +30,6 @@ public:
virtual void destroy();
virtual void shutdown();
- virtual void signalShutdown();
virtual void waitForShutdown();
virtual ObjectPrx stringToProxy(const std::string&);
@@ -81,15 +79,6 @@ private:
::IceInternal::InstancePtr _instance;
//
- // We need _serverThreadPool directly in CommunicatorI. That's
- // because the shutdown() operation is signal-safe, and thus must
- // not access any mutex locks or _instance. It may only access
- // _serverThreadPool->initiateShutdown(), which is signal-safe as
- // well.
- //
- ::IceInternal::ThreadPoolPtr _serverThreadPool;
-
- //
// We don't want the dynamic libraries to be unloaded until the
// Communicator's destructor is invoked.
//
diff --git a/cpp/src/Ice/ThreadPool.h b/cpp/src/Ice/ThreadPool.h
index 885a7f33008..1f514c6535f 100644
--- a/cpp/src/Ice/ThreadPool.h
+++ b/cpp/src/Ice/ThreadPool.h
@@ -48,11 +48,11 @@ public:
void _register(SOCKET, const EventHandlerPtr&);
void unregister(SOCKET);
void promoteFollower();
- void initiateShutdown(); // Signal-safe shutdown initiation.
void joinWithAllThreads();
private:
+ void initiateShutdown(); // Signal-safe shutdown initiation.
bool clearInterrupt();
void setInterrupt(char);
diff --git a/cpp/src/IceUtil/.depend b/cpp/src/IceUtil/.depend
index b29e659154e..be0e6e52ae6 100644
--- a/cpp/src/IceUtil/.depend
+++ b/cpp/src/IceUtil/.depend
@@ -1,11 +1,13 @@
Exception.o: Exception.cpp ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h
Unicode.o: Unicode.cpp ../../include/IceUtil/Unicode.h ../../include/IceUtil/Config.h
-UUID.o: UUID.cpp ../../include/IceUtil/UUID.h ../../include/IceUtil/Config.h ../../include/IceUtil/Unicode.h
+UUID.o: UUID.cpp ../../include/IceUtil/UUID.h ../../include/IceUtil/Config.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Unicode.h
RecMutex.o: RecMutex.cpp ../../include/IceUtil/RecMutex.h ../../include/IceUtil/Config.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h
RWRecMutex.o: RWRecMutex.cpp ../../include/IceUtil/RWRecMutex.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Config.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/IceUtil/Thread.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Handle.h
Cond.o: Cond.cpp ../../include/IceUtil/Cond.h ../../include/IceUtil/Config.h ../../include/IceUtil/Time.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h
Thread.o: Thread.cpp ../../include/IceUtil/Thread.h ../../include/IceUtil/Shared.h ../../include/IceUtil/Config.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Time.h
ThreadException.o: ThreadException.cpp ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h
+StaticMutex.o: StaticMutex.cpp ../../include/IceUtil/StaticMutex.h ../../include/IceUtil/Config.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h
+CtrlCHandler.o: CtrlCHandler.cpp ../../include/IceUtil/CtrlCHandler.h ../../include/IceUtil/Config.h ../../include/IceUtil/Exception.h ../../include/IceUtil/StaticMutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h
Time.o: Time.cpp ../../include/IceUtil/Time.h ../../include/IceUtil/Config.h
InputUtil.o: InputUtil.cpp ../../include/IceUtil/InputUtil.h ../../include/IceUtil/Config.h
OutputUtil.o: OutputUtil.cpp ../../include/IceUtil/OutputUtil.h ../../include/IceUtil/Config.h
diff --git a/cpp/src/IceUtil/CtrlCHandler.cpp b/cpp/src/IceUtil/CtrlCHandler.cpp
new file mode 100644
index 00000000000..9c7c53220dc
--- /dev/null
+++ b/cpp/src/IceUtil/CtrlCHandler.cpp
@@ -0,0 +1,208 @@
+// **********************************************************************
+//
+// Copyright (c) 2003
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <IceUtil/CtrlCHandler.h>
+#include <IceUtil/StaticMutex.h>
+
+#ifndef _WIN32
+# ifdef __sun
+# define _POSIX_PTHREAD_SEMANTICS
+# endif
+# include <signal.h>
+#endif
+
+using namespace std;
+using namespace IceUtil;
+
+static CtrlCHandlerCallback _callback = 0;
+static const CtrlCHandler* _handler = 0;
+
+CtrlCHandlerException::CtrlCHandlerException(const char* file, int line) :
+ Exception(file, line)
+{
+}
+
+string
+CtrlCHandlerException::ice_name() const
+{
+ return "IceUtil::CtrlCHandlerException";
+}
+
+Exception*
+CtrlCHandlerException::ice_clone() const
+{
+ return new CtrlCHandlerException(*this);
+}
+
+void
+CtrlCHandlerException::ice_throw() const
+{
+ throw *this;
+}
+
+void
+CtrlCHandler::setCallback(CtrlCHandlerCallback callback)
+{
+ StaticMutex::Lock lock(globalMutex);
+ _callback = callback;
+}
+
+CtrlCHandlerCallback
+CtrlCHandler::getCallback() const
+{
+ StaticMutex::Lock lock(globalMutex);
+ return _callback;
+}
+
+#ifdef _WIN32
+
+static BOOL WINAPI handlerRoutine(DWORD dwCtrlType)
+{
+ CtrlCHandlerCallback callback = _handler->getCallback();
+ if(callback != 0)
+ {
+ try
+ {
+ callback(dwCtrlType);
+ }
+ catch(...)
+ {
+ assert(0);
+ }
+ }
+ return TRUE;
+}
+
+
+CtrlCHandler::CtrlCHandler(CtrlCHandlerCallback callback)
+{
+ StaticMutex::Lock lock(globalMutex);
+ if(_handler != 0)
+ {
+ throw CtrlCHandlerException(__FILE__, __LINE__);
+ }
+ else
+ {
+ _callback = callback;
+ _handler = this;
+ lock.release();
+ SetConsoleCtrlHandler(handlerRoutine, TRUE);
+ }
+}
+
+CtrlCHandler::~CtrlCHandler()
+{
+ SetConsoleCtrlHandler(handlerRoutine, FALSE);
+ {
+ StaticMutex::Lock lock(globalMutex);
+ _handler = 0;
+ }
+}
+
+#else
+
+extern "C"
+{
+
+static void*
+sigwaitThread(void*)
+{
+ sigset_t ctrlCLikeSignals;
+ sigemptyset(&ctrlCLikeSignals);
+ sigaddset(&ctrlCLikeSignals, SIGHUP);
+ sigaddset(&ctrlCLikeSignals, SIGINT);
+ sigaddset(&ctrlCLikeSignals, SIGTERM);
+
+ // Run until I'm cancelled (in sigwait())
+ //
+ for(;;)
+ {
+ int signal = 0;
+ int rc = sigwait(&ctrlCLikeSignals, &signal);
+ assert(rc == 0);
+
+ rc = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
+ assert(rc == 0);
+
+ CtrlCHandlerCallback callback = _handler->getCallback();
+
+ if(callback != 0)
+ {
+ try
+ {
+ callback(signal);
+ }
+ catch(...)
+ {
+ assert(0);
+ }
+ }
+
+ rc = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
+ assert(rc == 0);
+ }
+ return 0;
+}
+}
+
+static pthread_t _tid;
+
+CtrlCHandler::CtrlCHandler(CtrlCHandlerCallback callback)
+{
+ StaticMutex::Lock lock(globalMutex);
+ if(_handler != 0)
+ {
+ throw CtrlCHandlerException(__FILE__, __LINE__);
+ }
+ else
+ {
+ _callback = callback;
+ _handler = this;
+ lock.release();
+
+ // We block these CTRL+C like signals in the main thread,
+ // and by default all other threads will inherit this signal
+ // disposition.
+
+ sigset_t ctrlCLikeSignals;
+ sigemptyset(&ctrlCLikeSignals);
+ sigaddset(&ctrlCLikeSignals, SIGHUP);
+ sigaddset(&ctrlCLikeSignals, SIGINT);
+ sigaddset(&ctrlCLikeSignals, SIGTERM);
+ int rc = pthread_sigmask(SIG_BLOCK, &ctrlCLikeSignals, 0);
+ assert(rc == 0);
+
+ // Joinable thread
+ rc = pthread_create(&_tid, 0, sigwaitThread, 0);
+ assert(rc == 0);
+ }
+}
+
+CtrlCHandler::~CtrlCHandler()
+{
+ int rc = pthread_cancel(_tid);
+ assert(rc == 0);
+ void* status = 0;
+ rc = pthread_join(_tid, &status);
+ assert(rc == 0);
+ assert(status == PTHREAD_CANCELED);
+
+ {
+ StaticMutex::Lock lock(globalMutex);
+ _handler = 0;
+ }
+}
+
+#endif
+
diff --git a/cpp/src/IceUtil/Makefile b/cpp/src/IceUtil/Makefile
index 88e1640354c..a448d7ec787 100644
--- a/cpp/src/IceUtil/Makefile
+++ b/cpp/src/IceUtil/Makefile
@@ -26,6 +26,8 @@ OBJS = Exception.o \
Cond.o \
Thread.o \
ThreadException.o \
+ StaticMutex.o \
+ CtrlCHandler.o \
Time.o \
InputUtil.o \
OutputUtil.o \
diff --git a/cpp/src/IceUtil/StaticMutex.cpp b/cpp/src/IceUtil/StaticMutex.cpp
new file mode 100644
index 00000000000..091aa5035f4
--- /dev/null
+++ b/cpp/src/IceUtil/StaticMutex.cpp
@@ -0,0 +1,79 @@
+// **********************************************************************
+//
+// Copyright (c) 2003
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <IceUtil/StaticMutex.h>
+#include <IceUtil/ThreadException.h>
+
+#ifdef _WIN32
+# include <list>
+# include <algorithm>
+
+using namespace std;
+
+static CRITICAL_SECTION _criticalSection;
+static list<CRITICAL_SECTION*>* _criticalSectionList;
+
+// Although apparently not documented by Microsoft, static objects are
+// initialized before DllMain/DLL_PROCESS_ATTACH and finalized after
+// DllMain/DLL_PROCESS_DETACH ... that's why we use a static object.
+
+namespace IceUtil
+{
+
+class Init
+{
+public:
+
+ Init();
+ ~Init();
+};
+
+static Init _init;
+
+
+Init::Init()
+{
+ InitializeCriticalSection(&_criticalSection);
+ _criticalSectionList = new list<CRITICAL_SECTION*>;
+}
+
+Init::~Init()
+{
+ for_each(_criticalSectionList->begin(), _criticalSectionList->end(),
+ DeleteCriticalSection);
+ delete _criticalSectionList;
+ DeleteCriticalSection(&_criticalSection);
+}
+}
+
+// For full thread-safety, we assume that _mutexInitialized cannot be seen as true
+// before CRITICAL_SECTION has been updated. This is true on x86. Does IA64
+// provide the same memory ordering guarantees?
+//
+void IceUtil::StaticMutex::initialize() const
+{
+ EnterCriticalSection(&_criticalSection);
+ if(!_mutexInitialized)
+ {
+ InitializeCriticalSection(&_mutex);
+ _mutexInitialized = true;
+ _criticalSectionList->push_back(&_mutex);
+ }
+ LeaveCriticalSection(&_criticalSection);
+}
+
+#endif
+
+IceUtil::StaticMutex IceUtil::globalMutex = ICE_STATIC_MUTEX_INITIALIZER;
+
diff --git a/cpp/src/IceUtil/iceutil.dsp b/cpp/src/IceUtil/iceutil.dsp
index 146da953868..f4a6eda142b 100644
--- a/cpp/src/IceUtil/iceutil.dsp
+++ b/cpp/src/IceUtil/iceutil.dsp
@@ -114,6 +114,10 @@ SOURCE=.\Cond.cpp
# End Source File
# Begin Source File
+SOURCE=.\CtrlCHandler.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\Exception.cpp
# End Source File
# Begin Source File
@@ -134,6 +138,10 @@ SOURCE=.\RWRecMutex.cpp
# End Source File
# Begin Source File
+SOURCE=.\StaticMutex.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\Thread.cpp
# End Source File
# Begin Source File
@@ -170,6 +178,10 @@ SOURCE=..\..\include\IceUtil\Config.h
# End Source File
# Begin Source File
+SOURCE=..\..\include\IceUtil\CtrlCHandler.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\include\IceUtil\Exception.h
# End Source File
# Begin Source File
@@ -218,6 +230,10 @@ SOURCE=..\..\include\IceUtil\Shared.h
# End Source File
# Begin Source File
+SOURCE=..\..\include\IceUtil\StaticMutex.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\include\IceUtil\Thread.h
# End Source File
# Begin Source File