summaryrefslogtreecommitdiff
path: root/cpp/src/IceUtil/CtrlCHandler.cpp
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2013-02-13 08:58:49 +0100
committerBenoit Foucher <benoit@zeroc.com>2013-02-13 08:58:49 +0100
commit6cf12fd32534e5c8f0ccedea90ff98e37f4c6ee6 (patch)
tree2665447290295ef628d05367cf84c8bd3ed47745 /cpp/src/IceUtil/CtrlCHandler.cpp
parentFixed ICE-5227 and ICE-5229: support for vc110_xp with Visual Studio 2012 (diff)
downloadice-6cf12fd32534e5c8f0ccedea90ff98e37f4c6ee6.tar.bz2
ice-6cf12fd32534e5c8f0ccedea90ff98e37f4c6ee6.tar.xz
ice-6cf12fd32534e5c8f0ccedea90ff98e37f4c6ee6.zip
Fixed ICE-4931 - Ctrl-C handler causing SEGFAULT on OpenSUSE/gcc 4.7
Diffstat (limited to 'cpp/src/IceUtil/CtrlCHandler.cpp')
-rw-r--r--cpp/src/IceUtil/CtrlCHandler.cpp80
1 files changed, 37 insertions, 43 deletions
diff --git a/cpp/src/IceUtil/CtrlCHandler.cpp b/cpp/src/IceUtil/CtrlCHandler.cpp
index 4123111264e..744c5e74ac3 100644
--- a/cpp/src/IceUtil/CtrlCHandler.cpp
+++ b/cpp/src/IceUtil/CtrlCHandler.cpp
@@ -98,7 +98,15 @@ CtrlCHandler::getCallback() const
static BOOL WINAPI handlerRoutine(DWORD dwCtrlType)
{
- CtrlCHandlerCallback callback = _handler->getCallback();
+ CtrlCHandlerCallback callback;
+ {
+ IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(globalMutex);
+ if(!_handler) // The handler is destroyed.
+ {
+ return FALSE;
+ }
+ callback = _callback;
+ }
if(callback != 0)
{
callback(dwCtrlType);
@@ -150,42 +158,36 @@ sigwaitThread(void*)
sigaddset(&ctrlCLikeSignals, SIGTERM);
//
- // Run until I'm cancelled (in sigwait())
+ // Run until the handler is destroyed (_handler == 0)
//
for(;;)
{
int signal = 0;
int rc = sigwait(&ctrlCLikeSignals, &signal);
-#if defined(__APPLE__)
- //
- // WORKAROUND: sigwait is not a cancelation point on OS X. To cancel this thread, the
- // destructor cancels the thread and send a signal to the thread to unblock sigwait, then
- // we explicitly test for cancellation.
- //
- pthread_testcancel();
-#endif
- //
- // Some sigwait() implementations incorrectly return EINTR
- // when interrupted by an unblocked caught signal
- //
if(rc == EINTR)
{
+ //
+ // Some sigwait() implementations incorrectly return EINTR
+ // when interrupted by an unblocked caught signal
+ //
continue;
}
assert(rc == 0);
- rc = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
- assert(rc == 0);
-
- CtrlCHandlerCallback callback = _handler->getCallback();
-
+ CtrlCHandlerCallback callback;
+ {
+ IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(globalMutex);
+ if(!_handler) // The handler is destroyed.
+ {
+ return 0;
+ }
+ callback = _callback;
+ }
+
if(callback != 0)
{
callback(signal);
}
-
- rc = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
- assert(rc == 0);
}
return 0;
}
@@ -243,36 +245,28 @@ CtrlCHandler::CtrlCHandler(CtrlCHandlerCallback callback)
CtrlCHandler::~CtrlCHandler()
{
-#ifndef NDEBUG
- int rc = pthread_cancel(_tid);
- assert(rc == 0);
-#else
- pthread_cancel(_tid);
-#endif
-#if defined(__APPLE__)
//
- // WORKAROUND: sigwait isn't a cancellation point on OS X, see
- // comment in sigwaitThread
+ // Clear the handler, the sigwaitThread will exit if _handler is
+ // nil.
//
- pthread_kill(_tid, SIGTERM);
- //assert(rc == 0); For some reaosns, this assert is sometime triggered
-#endif
- void* status = 0;
+ {
+ IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(globalMutex);
+ _handler = 0;
+ }
+ //
+ // Signal the sigwaitThread and join it.
+ //
+ void* status = 0;
#ifndef NDEBUG
+ int rc = pthread_kill(_tid, SIGTERM);
+ assert(rc == 0);
rc = pthread_join(_tid, &status);
assert(rc == 0);
#else
+ pthread_kill(_tid, SIGTERM);
pthread_join(_tid, &status);
#endif
-
-#if !defined(__APPLE__)
- assert(status == PTHREAD_CANCELED);
-#endif
- {
- IceUtilInternal::MutexPtrLock<IceUtil::Mutex> lock(globalMutex);
- _handler = 0;
- }
}
#endif