Author: cliffjansen Date: Sun Sep 30 19:23:37 2012 New Revision: 1392093 URL: http://svn.apache.org/viewvc?rev=1392093&view=rev Log: QPID-4330: Windows static destructors: threadSafeShutdown() test
Added: qpid/trunk/qpid/cpp/src/qpid/client/windows/ClientDllMain.cpp qpid/trunk/qpid/cpp/src/qpid/sys/windows/QpidDllMain.h Modified: qpid/trunk/qpid/cpp/include/qpid/sys/SystemInfo.h qpid/trunk/qpid/cpp/src/CMakeLists.txt qpid/trunk/qpid/cpp/src/Makefile.am qpid/trunk/qpid/cpp/src/qpid/client/ConnectionImpl.cpp qpid/trunk/qpid/cpp/src/qpid/sys/posix/SystemInfo.cpp qpid/trunk/qpid/cpp/src/qpid/sys/solaris/SystemInfo.cpp qpid/trunk/qpid/cpp/src/qpid/sys/windows/Socket.cpp qpid/trunk/qpid/cpp/src/qpid/sys/windows/SystemInfo.cpp qpid/trunk/qpid/cpp/src/qpid/sys/windows/Thread.cpp Modified: qpid/trunk/qpid/cpp/include/qpid/sys/SystemInfo.h URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/include/qpid/sys/SystemInfo.h?rev=1392093&r1=1392092&r2=1392093&view=diff ============================================================================== --- qpid/trunk/qpid/cpp/include/qpid/sys/SystemInfo.h (original) +++ qpid/trunk/qpid/cpp/include/qpid/sys/SystemInfo.h Sun Sep 30 19:23:37 2012 @@ -90,6 +90,12 @@ QPID_COMMON_EXTERN uint32_t getParentPro */ QPID_COMMON_EXTERN std::string getProcessName(); +/** + * Can thread related primitives be trusted during runtime house-cleaning? + * (i.e. static destructors, atexit()). + */ +QPID_COMMON_EXTERN bool threadSafeShutdown(); + }}} // namespace qpid::sys::SystemInfo Modified: qpid/trunk/qpid/cpp/src/CMakeLists.txt URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/CMakeLists.txt?rev=1392093&r1=1392092&r2=1392093&view=diff ============================================================================== --- qpid/trunk/qpid/cpp/src/CMakeLists.txt (original) +++ qpid/trunk/qpid/cpp/src/CMakeLists.txt Sun Sep 30 19:23:37 2012 @@ -766,6 +766,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL Windows) ) set (qpidclient_platform_SOURCES ${sslclient_windows_SOURCES} + qpid/client/windows/ClientDllMain.cpp ) set (qpidclient_platform_LIBS ${windows_ssl_libs} Modified: qpid/trunk/qpid/cpp/src/Makefile.am URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/Makefile.am?rev=1392093&r1=1392092&r2=1392093&view=diff ============================================================================== --- qpid/trunk/qpid/cpp/src/Makefile.am (original) +++ qpid/trunk/qpid/cpp/src/Makefile.am Sun Sep 30 19:23:37 2012 @@ -25,6 +25,7 @@ SUBDIRS = . tests windows_dist = \ qpid/client/windows/SaslFactory.cpp \ qpid/client/windows/SslConnector.cpp \ + qpid/client/windows/ClientDllMain.cpp \ qpid/log/windows/SinkOptions.cpp \ qpid/log/windows/SinkOptions.h \ ../include/qpid/sys/windows/check.h \ @@ -42,6 +43,7 @@ windows_dist = \ qpid/sys/windows/PollableCondition.cpp \ qpid/sys/windows/PipeHandle.cpp \ ../include/qpid/sys/windows/Mutex.h \ + qpid/sys/windows/QpidDllMain.h \ qpid/sys/windows/Shlib.cpp \ qpid/sys/windows/SocketAddress.cpp \ qpid/sys/windows/Socket.cpp \ Modified: qpid/trunk/qpid/cpp/src/qpid/client/ConnectionImpl.cpp URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/client/ConnectionImpl.cpp?rev=1392093&r1=1392092&r2=1392093&view=diff ============================================================================== --- qpid/trunk/qpid/cpp/src/qpid/client/ConnectionImpl.cpp (original) +++ qpid/trunk/qpid/cpp/src/qpid/client/ConnectionImpl.cpp Sun Sep 30 19:23:37 2012 @@ -128,15 +128,17 @@ public: // and we can't do that before we're unloaded as we can't // restart the Poller after shutting it down ~IOThread() { - std::vector<Thread> threads; - { - ScopedLock<Mutex> l(threadLock); - if (poller_) - poller_->shutdown(); - t.swap(threads); - } - for (std::vector<Thread>::iterator i = threads.begin(); i != threads.end(); ++i) { - i->join(); + if (SystemInfo::threadSafeShutdown()) { + std::vector<Thread> threads; + { + ScopedLock<Mutex> l(threadLock); + if (poller_) + poller_->shutdown(); + t.swap(threads); + } + for (std::vector<Thread>::iterator i = threads.begin(); i != threads.end(); ++i) { + i->join(); + } } } }; Added: qpid/trunk/qpid/cpp/src/qpid/client/windows/ClientDllMain.cpp URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/client/windows/ClientDllMain.cpp?rev=1392093&view=auto ============================================================================== --- qpid/trunk/qpid/cpp/src/qpid/client/windows/ClientDllMain.cpp (added) +++ qpid/trunk/qpid/cpp/src/qpid/client/windows/ClientDllMain.cpp Sun Sep 30 19:23:37 2012 @@ -0,0 +1,22 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "qpid/sys/windows/QpidDllMain.h" Modified: qpid/trunk/qpid/cpp/src/qpid/sys/posix/SystemInfo.cpp URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/sys/posix/SystemInfo.cpp?rev=1392093&r1=1392092&r2=1392093&view=diff ============================================================================== --- qpid/trunk/qpid/cpp/src/qpid/sys/posix/SystemInfo.cpp (original) +++ qpid/trunk/qpid/cpp/src/qpid/sys/posix/SystemInfo.cpp Sun Sep 30 19:23:37 2012 @@ -205,4 +205,11 @@ string SystemInfo::getProcessName() return value; } +// Always true. Only Windows has exception cases. +bool SystemInfo::threadSafeShutdown() +{ + return true; +} + + }} // namespace qpid::sys Modified: qpid/trunk/qpid/cpp/src/qpid/sys/solaris/SystemInfo.cpp URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/sys/solaris/SystemInfo.cpp?rev=1392093&r1=1392092&r2=1392093&view=diff ============================================================================== --- qpid/trunk/qpid/cpp/src/qpid/sys/solaris/SystemInfo.cpp (original) +++ qpid/trunk/qpid/cpp/src/qpid/sys/solaris/SystemInfo.cpp Sun Sep 30 19:23:37 2012 @@ -126,4 +126,10 @@ string SystemInfo::getProcessName() return value; } +// Always true. Only Windows has exception cases. +bool SystemInfo::threadSafeShutdown() +{ + return true; +} + }} // namespace qpid::sys Added: qpid/trunk/qpid/cpp/src/qpid/sys/windows/QpidDllMain.h URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/sys/windows/QpidDllMain.h?rev=1392093&view=auto ============================================================================== --- qpid/trunk/qpid/cpp/src/qpid/sys/windows/QpidDllMain.h (added) +++ qpid/trunk/qpid/cpp/src/qpid/sys/windows/QpidDllMain.h Sun Sep 30 19:23:37 2012 @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/* + * Include this file once in each DLL that relies on SystemInfo.h: + * threadSafeShutdown(). Note that Thread.cpp has a more elaborate + * DllMain, that also provides this functionality separately. + * + * Teardown is in the reverse order of the DLL dependencies used + * during the load phase. The calls to DllMain and the static + * destructors are from the same thread, so no locking is necessary + * and there is no downside to an invocation of DllMain by multiple + * Qpid DLLs. + */ + +#ifdef _DLL + +#include <qpid/ImportExport.h> +#include <windows.h> + +namespace qpid { +namespace sys { +namespace windows { + +QPID_IMPORT bool processExiting; +QPID_IMPORT bool libraryUnloading; + +}}} // namespace qpid::sys::SystemInfo + + +BOOL APIENTRY DllMain(HMODULE hm, DWORD reason, LPVOID reserved) { + switch (reason) { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + // Remember how the process is terminating this DLL. + if (reserved != NULL) { + qpid::sys::windows::processExiting = true; + // Danger: all threading suspect, including indirect use of malloc or locks. + // Think twice before adding more functionality here. + return TRUE; + } + else { + qpid::sys::windows::libraryUnloading = true; + } + break; + } + return TRUE; +} + + +#endif Modified: qpid/trunk/qpid/cpp/src/qpid/sys/windows/Socket.cpp URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Socket.cpp?rev=1392093&r1=1392092&r2=1392093&view=diff ============================================================================== --- qpid/trunk/qpid/cpp/src/qpid/sys/windows/Socket.cpp (original) +++ qpid/trunk/qpid/cpp/src/qpid/sys/windows/Socket.cpp Sun Sep 30 19:23:37 2012 @@ -24,6 +24,7 @@ #include "qpid/sys/SocketAddress.h" #include "qpid/sys/windows/check.h" #include "qpid/sys/windows/IoHandlePrivate.h" +#include "qpid/sys/SystemInfo.h" // Ensure we get all of winsock2.h #ifndef _WIN32_WINNT @@ -67,7 +68,8 @@ public: } ~WinSockSetup() { - WSACleanup(); + if (SystemInfo::threadSafeShutdown()) + WSACleanup(); } public: Modified: qpid/trunk/qpid/cpp/src/qpid/sys/windows/SystemInfo.cpp URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/sys/windows/SystemInfo.cpp?rev=1392093&r1=1392092&r2=1392093&view=diff ============================================================================== --- qpid/trunk/qpid/cpp/src/qpid/sys/windows/SystemInfo.cpp (original) +++ qpid/trunk/qpid/cpp/src/qpid/sys/windows/SystemInfo.cpp Sun Sep 30 19:23:37 2012 @@ -25,7 +25,8 @@ #include "qpid/sys/SystemInfo.h" #include "qpid/sys/IntegerTypes.h" -#include "qpid/Exception.h" +#include "qpid/Exception.h" +#include "qpid/log/Statement.h" #include <assert.h> #include <winsock2.h> @@ -208,4 +209,29 @@ std::string SystemInfo::getProcessName() return name; } + +#ifdef _DLL +namespace windows { +// set from one or more Qpid DLLs: i.e. in DllMain with DLL_PROCESS_DETACH +QPID_EXPORT bool processExiting = false; +QPID_EXPORT bool libraryUnloading = false; +} +#endif + +bool SystemInfo::threadSafeShutdown() +{ +#ifdef _DLL + if (!windows::processExiting && !windows::libraryUnloading) { + // called before exit() or FreeLibrary(), or by a DLL without + // a participating DllMain. + QPID_LOG(warning, "invalid query for shutdown state"); + throw qpid::Exception(QPID_MSG("Unable to determine shutdown state.")); + } + return !windows::processExiting; +#else + // Not a DLL: shutdown can only be by exit() or return from main(). + return false; +#endif +} + }} // namespace qpid::sys Modified: qpid/trunk/qpid/cpp/src/qpid/sys/windows/Thread.cpp URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Thread.cpp?rev=1392093&r1=1392092&r2=1392093&view=diff ============================================================================== --- qpid/trunk/qpid/cpp/src/qpid/sys/windows/Thread.cpp (original) +++ qpid/trunk/qpid/cpp/src/qpid/sys/windows/Thread.cpp Sun Sep 30 19:23:37 2012 @@ -27,6 +27,7 @@ #include "qpid/sys/Thread.h" #include "qpid/sys/Runnable.h" #include "qpid/sys/windows/check.h" +#include "qpid/sys/SystemInfo.h" #include <process.h> #include <windows.h> @@ -274,8 +275,17 @@ Thread Thread::current() { #ifdef _DLL +namespace qpid { +namespace sys { +namespace windows { + +extern bool processExiting; +extern bool libraryUnloading; + +}}} // namespace qpid::sys::SystemInfo + // DllMain: called possibly many times in a process lifetime if dll -// loaded and freed repeatedly . Be mindful of Windows loader lock +// loaded and freed repeatedly. Be mindful of Windows loader lock // and other DllMain restrictions. BOOL APIENTRY DllMain(HMODULE hm, DWORD reason, LPVOID reserved) { @@ -290,10 +300,12 @@ BOOL APIENTRY DllMain(HMODULE hm, DWORD if (reserved != NULL) { // process exit(): threads are stopped arbitrarily and // possibly in an inconsistent state. Not even threadLock - // can be trusted. All static destructors have been - // called at this point and any resources this unit knows - // about will be released as part of process tear down by - // the OS. Accordingly, do nothing. + // can be trusted. All static destructors for this unit + // are pending and face the same unsafe environment. + // Any resources this unit knows about will be released as + // part of process tear down by the OS. Accordingly, skip + // any clean up tasks. + qpid::sys::windows::processExiting = true; return TRUE; } else { @@ -301,6 +313,7 @@ BOOL APIENTRY DllMain(HMODULE hm, DWORD // encouraged to clean up to avoid leaks. Mostly we just // want any straggler threads to finish and notify // threadsDone as the last thing they do. + qpid::sys::windows::libraryUnloading = true; while (1) { { ScopedCriticalSection l(threadLock); --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org