diff options
author | Benoit Foucher <benoit@zeroc.com> | 2013-02-13 08:58:49 +0100 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2013-02-13 08:58:49 +0100 |
commit | 6cf12fd32534e5c8f0ccedea90ff98e37f4c6ee6 (patch) | |
tree | 2665447290295ef628d05367cf84c8bd3ed47745 /cpp/src/IceUtil/CtrlCHandler.cpp | |
parent | Fixed ICE-5227 and ICE-5229: support for vc110_xp with Visual Studio 2012 (diff) | |
download | ice-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.cpp | 80 |
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 |