summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorClifford Allan Jansen <cliffjansen@apache.org>2012-09-30 19:23:37 +0000
committerClifford Allan Jansen <cliffjansen@apache.org>2012-09-30 19:23:37 +0000
commit694a0fb6c874a1bbf1d3eeeca6c18952a78b9f28 (patch)
tree7f3456ac3134c777c609d43fc53ae3d7feaf4fff /cpp/src
parent09818cb3d22e99ca30f1fafb7e296ba0b2e9f622 (diff)
downloadqpid-python-694a0fb6c874a1bbf1d3eeeca6c18952a78b9f28.tar.gz
QPID-4330: Windows static destructors: threadSafeShutdown() test
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1392093 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/CMakeLists.txt1
-rw-r--r--cpp/src/Makefile.am2
-rw-r--r--cpp/src/qpid/client/ConnectionImpl.cpp20
-rw-r--r--cpp/src/qpid/client/windows/ClientDllMain.cpp22
-rwxr-xr-xcpp/src/qpid/sys/posix/SystemInfo.cpp7
-rwxr-xr-xcpp/src/qpid/sys/solaris/SystemInfo.cpp6
-rw-r--r--cpp/src/qpid/sys/windows/QpidDllMain.h72
-rw-r--r--cpp/src/qpid/sys/windows/Socket.cpp4
-rwxr-xr-xcpp/src/qpid/sys/windows/SystemInfo.cpp28
-rwxr-xr-xcpp/src/qpid/sys/windows/Thread.cpp23
10 files changed, 169 insertions, 16 deletions
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt
index 21e82a97b9..299990a6e8 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -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}
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am
index c39dd8114c..45c0d0fb77 100644
--- a/cpp/src/Makefile.am
+++ b/cpp/src/Makefile.am
@@ -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 \
diff --git a/cpp/src/qpid/client/ConnectionImpl.cpp b/cpp/src/qpid/client/ConnectionImpl.cpp
index 85b0e8303e..0abfbe09ec 100644
--- a/cpp/src/qpid/client/ConnectionImpl.cpp
+++ b/cpp/src/qpid/client/ConnectionImpl.cpp
@@ -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();
+ }
}
}
};
diff --git a/cpp/src/qpid/client/windows/ClientDllMain.cpp b/cpp/src/qpid/client/windows/ClientDllMain.cpp
new file mode 100644
index 0000000000..d636489908
--- /dev/null
+++ b/cpp/src/qpid/client/windows/ClientDllMain.cpp
@@ -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"
diff --git a/cpp/src/qpid/sys/posix/SystemInfo.cpp b/cpp/src/qpid/sys/posix/SystemInfo.cpp
index cfd2c64aee..dea74b4ab0 100755
--- a/cpp/src/qpid/sys/posix/SystemInfo.cpp
+++ b/cpp/src/qpid/sys/posix/SystemInfo.cpp
@@ -205,4 +205,11 @@ string SystemInfo::getProcessName()
return value;
}
+// Always true. Only Windows has exception cases.
+bool SystemInfo::threadSafeShutdown()
+{
+ return true;
+}
+
+
}} // namespace qpid::sys
diff --git a/cpp/src/qpid/sys/solaris/SystemInfo.cpp b/cpp/src/qpid/sys/solaris/SystemInfo.cpp
index e5856f55e6..d4b18e66c8 100755
--- a/cpp/src/qpid/sys/solaris/SystemInfo.cpp
+++ b/cpp/src/qpid/sys/solaris/SystemInfo.cpp
@@ -126,4 +126,10 @@ string SystemInfo::getProcessName()
return value;
}
+// Always true. Only Windows has exception cases.
+bool SystemInfo::threadSafeShutdown()
+{
+ return true;
+}
+
}} // namespace qpid::sys
diff --git a/cpp/src/qpid/sys/windows/QpidDllMain.h b/cpp/src/qpid/sys/windows/QpidDllMain.h
new file mode 100644
index 0000000000..74eaf0256a
--- /dev/null
+++ b/cpp/src/qpid/sys/windows/QpidDllMain.h
@@ -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
diff --git a/cpp/src/qpid/sys/windows/Socket.cpp b/cpp/src/qpid/sys/windows/Socket.cpp
index a4374260cc..17e3212a46 100644
--- a/cpp/src/qpid/sys/windows/Socket.cpp
+++ b/cpp/src/qpid/sys/windows/Socket.cpp
@@ -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:
diff --git a/cpp/src/qpid/sys/windows/SystemInfo.cpp b/cpp/src/qpid/sys/windows/SystemInfo.cpp
index cef78dcc60..282bbb7e24 100755
--- a/cpp/src/qpid/sys/windows/SystemInfo.cpp
+++ b/cpp/src/qpid/sys/windows/SystemInfo.cpp
@@ -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
diff --git a/cpp/src/qpid/sys/windows/Thread.cpp b/cpp/src/qpid/sys/windows/Thread.cpp
index 23b0033be4..b342c9da1d 100755
--- a/cpp/src/qpid/sys/windows/Thread.cpp
+++ b/cpp/src/qpid/sys/windows/Thread.cpp
@@ -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 reason, LPVOID reserved) {
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 reason, LPVOID reserved) {
// 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);