You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by cl...@apache.org on 2012/09/30 21:23:38 UTC

svn commit: r1392093 - in /qpid/trunk/qpid/cpp: include/qpid/sys/ src/ src/qpid/client/ src/qpid/client/windows/ src/qpid/sys/posix/ src/qpid/sys/solaris/ src/qpid/sys/windows/

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-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org