diff options
Diffstat (limited to 'cpp/src/qpid/sys/windows')
| -rw-r--r-- | cpp/src/qpid/sys/windows/AsynchIO.cpp | 71 | ||||
| -rwxr-xr-x | cpp/src/qpid/sys/windows/AsynchIoResult.h | 6 | ||||
| -rwxr-xr-x | cpp/src/qpid/sys/windows/IocpPoller.cpp | 6 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/windows/SCM.cpp | 332 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/windows/SCM.h | 111 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/windows/Shlib.cpp | 3 | ||||
| -rwxr-xr-x[-rw-r--r--] | cpp/src/qpid/sys/windows/Socket.cpp | 188 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/windows/SocketAddress.cpp | 120 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/windows/SslAsynchIO.h | 3 | ||||
| -rwxr-xr-x | cpp/src/qpid/sys/windows/StrError.cpp | 7 | ||||
| -rwxr-xr-x | cpp/src/qpid/sys/windows/Thread.cpp | 285 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/windows/Time.cpp | 36 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/windows/mingw32_compat.h | 39 | ||||
| -rw-r--r-- | cpp/src/qpid/sys/windows/uuid.cpp | 6 |
14 files changed, 217 insertions, 996 deletions
diff --git a/cpp/src/qpid/sys/windows/AsynchIO.cpp b/cpp/src/qpid/sys/windows/AsynchIO.cpp index 30378d4c5f..38d8842521 100644 --- a/cpp/src/qpid/sys/windows/AsynchIO.cpp +++ b/cpp/src/qpid/sys/windows/AsynchIO.cpp @@ -30,7 +30,6 @@ #include "qpid/log/Statement.h" #include "qpid/sys/windows/check.h" -#include "qpid/sys/windows/mingw32_compat.h" #include <boost/thread/once.hpp> @@ -47,13 +46,16 @@ namespace { /* * The function pointers for AcceptEx and ConnectEx need to be looked up - * at run time. + * at run time. Make sure this is done only once. */ -const LPFN_ACCEPTEX lookUpAcceptEx(const qpid::sys::Socket& s) { - SOCKET h = toSocketHandle(s); +boost::once_flag lookUpAcceptExOnce = BOOST_ONCE_INIT; +LPFN_ACCEPTEX fnAcceptEx = 0; +typedef void (*lookUpFunc)(const qpid::sys::Socket &); + +void lookUpAcceptEx() { + SOCKET h = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); GUID guidAcceptEx = WSAID_ACCEPTEX; DWORD dwBytes = 0; - LPFN_ACCEPTEX fnAcceptEx; WSAIoctl(h, SIO_GET_EXTENSION_FUNCTION_POINTER, &guidAcceptEx, @@ -63,9 +65,9 @@ const LPFN_ACCEPTEX lookUpAcceptEx(const qpid::sys::Socket& s) { &dwBytes, NULL, NULL); + closesocket(h); if (fnAcceptEx == 0) throw qpid::Exception(QPID_MSG("Failed to look up AcceptEx")); - return fnAcceptEx; } } @@ -92,15 +94,18 @@ private: AsynchAcceptor::Callback acceptedCallback; const Socket& socket; - const LPFN_ACCEPTEX fnAcceptEx; }; AsynchAcceptor::AsynchAcceptor(const Socket& s, Callback callback) : acceptedCallback(callback), - socket(s), - fnAcceptEx(lookUpAcceptEx(s)) { + socket(s) { s.setNonblocking(); +#if (BOOST_VERSION >= 103500) /* boost 1.35 or later reversed the args */ + boost::call_once(lookUpAcceptExOnce, lookUpAcceptEx); +#else + boost::call_once(lookUpAcceptEx, lookUpAcceptExOnce); +#endif } AsynchAcceptor::~AsynchAcceptor() @@ -109,8 +114,7 @@ AsynchAcceptor::~AsynchAcceptor() } void AsynchAcceptor::start(Poller::shared_ptr poller) { - PollerHandle ph = PollerHandle(socket); - poller->monitorHandle(ph, Poller::INPUT); + poller->monitorHandle(PollerHandle(socket), Poller::INPUT); restart (); } @@ -118,26 +122,25 @@ void AsynchAcceptor::restart(void) { DWORD bytesReceived = 0; // Not used, needed for AcceptEx API AsynchAcceptResult *result = new AsynchAcceptResult(acceptedCallback, this, - socket); + toSocketHandle(socket)); BOOL status; - status = fnAcceptEx(toSocketHandle(socket), - toSocketHandle(*result->newSocket), - result->addressBuffer, - 0, - AsynchAcceptResult::SOCKADDRMAXLEN, - AsynchAcceptResult::SOCKADDRMAXLEN, - &bytesReceived, - result->overlapped()); + status = ::fnAcceptEx(toSocketHandle(socket), + toSocketHandle(*result->newSocket), + result->addressBuffer, + 0, + AsynchAcceptResult::SOCKADDRMAXLEN, + AsynchAcceptResult::SOCKADDRMAXLEN, + &bytesReceived, + result->overlapped()); QPID_WINDOWS_CHECK_ASYNC_START(status); } AsynchAcceptResult::AsynchAcceptResult(AsynchAcceptor::Callback cb, AsynchAcceptor *acceptor, - const Socket& listener) - : callback(cb), acceptor(acceptor), - listener(toSocketHandle(listener)), - newSocket(listener.createSameTypeSocket()) { + SOCKET listener) + : callback(cb), acceptor(acceptor), listener(listener) { + newSocket.reset (new Socket()); } void AsynchAcceptResult::success(size_t /*bytesTransferred*/) { @@ -151,7 +154,7 @@ void AsynchAcceptResult::success(size_t /*bytesTransferred*/) { delete this; } -void AsynchAcceptResult::failure(int /*status*/) { +void AsynchAcceptResult::failure(int status) { //if (status != WSA_OPERATION_ABORTED) // Can there be anything else? ; delete this; @@ -170,20 +173,20 @@ private: FailedCallback failCallback; const Socket& socket; const std::string hostname; - const std::string port; + const uint16_t port; public: AsynchConnector(const Socket& socket, - const std::string& hostname, - const std::string& port, + std::string hostname, + uint16_t port, ConnectedCallback connCb, FailedCallback failCb = 0); void start(Poller::shared_ptr poller); }; AsynchConnector::AsynchConnector(const Socket& sock, - const std::string& hname, - const std::string& p, + std::string hname, + uint16_t p, ConnectedCallback connCb, FailedCallback failCb) : connCallback(connCb), failCallback(failCb), socket(sock), @@ -213,8 +216,8 @@ AsynchAcceptor* AsynchAcceptor::create(const Socket& s, } AsynchConnector* qpid::sys::AsynchConnector::create(const Socket& s, - const std::string& hostname, - const std::string& port, + std::string hostname, + uint16_t port, ConnectedCallback connCb, FailedCallback failCb) { @@ -407,9 +410,8 @@ void AsynchIO::queueForDeletion() { } void AsynchIO::start(Poller::shared_ptr poller0) { - PollerHandle ph = PollerHandle(socket); poller = poller0; - poller->monitorHandle(ph, Poller::INPUT); + poller->monitorHandle(PollerHandle(socket), Poller::INPUT); if (writeQueue.size() > 0) // Already have data queued for write notifyPendingWrite(); startReading(); @@ -582,6 +584,7 @@ void AsynchIO::notifyIdle(void) { void AsynchIO::startWrite(AsynchIO::BufferBase* buff) { writeInProgress = true; InterlockedIncrement(&opsInProgress); + int writeCount = buff->byteCount-buff->dataCount; AsynchWriteResult *result = new AsynchWriteResult(boost::bind(&AsynchIO::completion, this, _1), buff, diff --git a/cpp/src/qpid/sys/windows/AsynchIoResult.h b/cpp/src/qpid/sys/windows/AsynchIoResult.h index 27e4c22138..66c89efc11 100755 --- a/cpp/src/qpid/sys/windows/AsynchIoResult.h +++ b/cpp/src/qpid/sys/windows/AsynchIoResult.h @@ -83,22 +83,22 @@ class AsynchAcceptResult : public AsynchResult { public: AsynchAcceptResult(qpid::sys::AsynchAcceptor::Callback cb, AsynchAcceptor *acceptor, - const qpid::sys::Socket& listener); + SOCKET listener); virtual void success (size_t bytesTransferred); virtual void failure (int error); private: virtual void complete(void) {} // No-op for this class. + std::auto_ptr<qpid::sys::Socket> newSocket; qpid::sys::AsynchAcceptor::Callback callback; AsynchAcceptor *acceptor; SOCKET listener; - std::auto_ptr<qpid::sys::Socket> newSocket; // AcceptEx needs a place to write the local and remote addresses // when accepting the connection. Place those here; get enough for // IPv6 addresses, even if the socket is IPv4. - enum { SOCKADDRMAXLEN = sizeof(sockaddr_in6) + 16, + enum { SOCKADDRMAXLEN = sizeof sockaddr_in6 + 16, SOCKADDRBUFLEN = 2 * SOCKADDRMAXLEN }; char addressBuffer[SOCKADDRBUFLEN]; }; diff --git a/cpp/src/qpid/sys/windows/IocpPoller.cpp b/cpp/src/qpid/sys/windows/IocpPoller.cpp index 1805dd2cd8..d326ab02ac 100755 --- a/cpp/src/qpid/sys/windows/IocpPoller.cpp +++ b/cpp/src/qpid/sys/windows/IocpPoller.cpp @@ -152,9 +152,9 @@ void Poller::monitorHandle(PollerHandle& handle, Direction dir) { } // All no-ops... -void Poller::unmonitorHandle(PollerHandle& /*handle*/, Direction /*dir*/) {} -void Poller::registerHandle(PollerHandle& /*handle*/) {} -void Poller::unregisterHandle(PollerHandle& /*handle*/) {} +void Poller::unmonitorHandle(PollerHandle& handle, Direction dir) {} +void Poller::registerHandle(PollerHandle& handle) {} +void Poller::unregisterHandle(PollerHandle& handle) {} Poller::Event Poller::wait(Duration timeout) { DWORD timeoutMs = 0; diff --git a/cpp/src/qpid/sys/windows/SCM.cpp b/cpp/src/qpid/sys/windows/SCM.cpp deleted file mode 100644 index 4d2c74d4b9..0000000000 --- a/cpp/src/qpid/sys/windows/SCM.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/* - * - * 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/log/Statement.h" -#include "qpid/sys/windows/check.h" -#include "SCM.h" - -#pragma comment(lib, "advapi32.lib") - -namespace { - -// Container that will close a SC_HANDLE upon destruction. -class AutoServiceHandle { -public: - AutoServiceHandle(SC_HANDLE h_ = NULL) : h(h_) {} - ~AutoServiceHandle() { if (h != NULL) ::CloseServiceHandle(h); } - void release() { h = NULL; } - void reset(SC_HANDLE newHandle) - { - if (h != NULL) - ::CloseServiceHandle(h); - h = newHandle; - } - operator SC_HANDLE() const { return h; } - -private: - SC_HANDLE h; -}; - -} - -namespace qpid { -namespace windows { - -SCM::SCM() : scmHandle(NULL) -{ -} - -SCM::~SCM() -{ - if (NULL != scmHandle) - ::CloseServiceHandle(scmHandle); -} - -/** - * Install this executable as a service - */ -void SCM::install(const string& serviceName, - const string& serviceDesc, - const string& args, - DWORD startType, - const string& account, - const string& password, - const string& depends) -{ - // Handle dependent service name list; Windows wants a set of nul-separated - // names ending with a double nul. - string depends2 = depends; - if (!depends2.empty()) { - // CDL to null delimiter w/ trailing double null - size_t p = 0; - while ((p = depends2.find_first_of( ',', p)) != string::npos) - depends2.replace(p, 1, 1, '\0'); - depends2.push_back('\0'); - depends2.push_back('\0'); - } - -#if 0 - // I'm nervous about adding a user/password check here. Is this a - // potential attack vector, letting users check passwords without - // control? -Steve Huston, Feb 24, 2011 - - // Validate account, password - HANDLE hToken = NULL; - bool logStatus = false; - if (!account.empty() && !password.empty() && - !(logStatus = ::LogonUserA(account.c_str(), - "", - password.c_str(), - LOGON32_LOGON_NETWORK, - LOGON32_PROVIDER_DEFAULT, - &hToken ) != 0)) - std::cout << "warning: supplied account & password failed with LogonUser." << std::endl; - if (logStatus) - ::CloseHandle(hToken); -#endif - - // Get fully qualified .exe name - char myPath[MAX_PATH]; - DWORD myPathLength = ::GetModuleFileName(NULL, myPath, MAX_PATH); - QPID_WINDOWS_CHECK_NOT(myPathLength, 0); - string imagePath(myPath, myPathLength); - if (!args.empty()) - imagePath += " " + args; - - // Ensure there's a handle to the SCM database. - openSvcManager(); - - // Create the service - SC_HANDLE svcHandle; - svcHandle = ::CreateService(scmHandle, // SCM database - serviceName.c_str(), // name of service - serviceDesc.c_str(), // name to display - SERVICE_ALL_ACCESS, // desired access - SERVICE_WIN32_OWN_PROCESS, // service type - startType, // start type - SERVICE_ERROR_NORMAL, // error cntrl type - imagePath.c_str(), // path to service's binary w/ optional arguments - NULL, // no load ordering group - NULL, // no tag identifier - depends2.empty() ? NULL : depends2.c_str(), - account.empty() ? NULL : account.c_str(), // account name, or NULL for LocalSystem - password.empty() ? NULL : password.c_str()); // password, or NULL for none - QPID_WINDOWS_CHECK_NULL(svcHandle); - ::CloseServiceHandle(svcHandle); - QPID_LOG(info, "Service installed successfully"); -} - -/** - * - */ -void SCM::uninstall(const string& serviceName) -{ - // Ensure there's a handle to the SCM database. - openSvcManager(); - AutoServiceHandle svc(::OpenService(scmHandle, - serviceName.c_str(), - DELETE)); - QPID_WINDOWS_CHECK_NULL((SC_HANDLE)svc); - QPID_WINDOWS_CHECK_NOT(::DeleteService(svc), 0); - QPID_LOG(info, "Service deleted successfully."); -} - -/** - * Attempt to start the service. - */ -void SCM::start(const string& serviceName) -{ - // Ensure we have a handle to the SCM database. - openSvcManager(); - - // Get a handle to the service. - AutoServiceHandle svc(::OpenService(scmHandle, - serviceName.c_str(), - SERVICE_ALL_ACCESS)); - QPID_WINDOWS_CHECK_NULL(svc); - - // Check the status in case the service is not stopped. - DWORD state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING); - if (state == SERVICE_STOP_PENDING) - throw qpid::Exception("Timed out waiting for running service to stop."); - - // Attempt to start the service. - QPID_WINDOWS_CHECK_NOT(::StartService(svc, 0, NULL), 0); - - QPID_LOG(info, "Service start pending..."); - - // Check the status until the service is no longer start pending. - state = waitForStateChangeFrom(svc, SERVICE_START_PENDING); - // Determine whether the service is running. - if (state == SERVICE_RUNNING) { - QPID_LOG(info, "Service started successfully"); - } - else { - throw qpid::Exception(QPID_MSG("Service not yet running; state now " << state)); - } -} - -/** - * - */ -void SCM::stop(const string& serviceName) -{ - // Ensure a handle to the SCM database. - openSvcManager(); - - // Get a handle to the service. - AutoServiceHandle svc(::OpenService(scmHandle, - serviceName.c_str(), - SERVICE_STOP | SERVICE_QUERY_STATUS | - SERVICE_ENUMERATE_DEPENDENTS)); - QPID_WINDOWS_CHECK_NULL(svc); - - // Make sure the service is not already stopped; if it's stop-pending, - // wait for it to finalize. - DWORD state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING); - if (state == SERVICE_STOPPED) { - QPID_LOG(info, "Service is already stopped"); - return; - } - - // If the service is running, dependencies must be stopped first. - std::auto_ptr<ENUM_SERVICE_STATUS> deps; - DWORD numDeps = getDependentServices(svc, deps); - for (DWORD i = 0; i < numDeps; i++) - stop(deps.get()[i].lpServiceName); - - // Dependents stopped; send a stop code to the service. - SERVICE_STATUS_PROCESS ssp; - if (!::ControlService(svc, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssp)) - throw qpid::Exception(QPID_MSG("Stopping " << serviceName << ": " << - qpid::sys::strError(::GetLastError()))); - - // Wait for the service to stop. - state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING); - if (state == SERVICE_STOPPED) - QPID_LOG(info, QPID_MSG("Service " << serviceName << - " stopped successfully.")); -} - -/** - * - */ -void SCM::openSvcManager() -{ - if (NULL != scmHandle) - return; - - scmHandle = ::OpenSCManager(NULL, // local computer - NULL, // ServicesActive database - SC_MANAGER_ALL_ACCESS); // Rights - QPID_WINDOWS_CHECK_NULL(scmHandle); -} - -DWORD SCM::waitForStateChangeFrom(SC_HANDLE svc, DWORD originalState) -{ - SERVICE_STATUS_PROCESS ssStatus; - DWORD bytesNeeded; - DWORD waitTime; - if (!::QueryServiceStatusEx(svc, // handle to service - SC_STATUS_PROCESS_INFO, // information level - (LPBYTE)&ssStatus, // address of structure - sizeof(ssStatus), // size of structure - &bytesNeeded)) // size needed if buffer is too small - throw QPID_WINDOWS_ERROR(::GetLastError()); - - // Save the tick count and initial checkpoint. - DWORD startTickCount = ::GetTickCount(); - DWORD oldCheckPoint = ssStatus.dwCheckPoint; - - // Wait for the service to change out of the noted state. - while (ssStatus.dwCurrentState == originalState) { - // Do not wait longer than the wait hint. A good interval is - // one-tenth of the wait hint but not less than 1 second - // and not more than 10 seconds. - waitTime = ssStatus.dwWaitHint / 10; - if (waitTime < 1000) - waitTime = 1000; - else if (waitTime > 10000) - waitTime = 10000; - - ::Sleep(waitTime); - - // Check the status until the service is no longer stop pending. - if (!::QueryServiceStatusEx(svc, - SC_STATUS_PROCESS_INFO, - (LPBYTE) &ssStatus, - sizeof(ssStatus), - &bytesNeeded)) - throw QPID_WINDOWS_ERROR(::GetLastError()); - - if (ssStatus.dwCheckPoint > oldCheckPoint) { - // Continue to wait and check. - startTickCount = ::GetTickCount(); - oldCheckPoint = ssStatus.dwCheckPoint; - } else { - if ((::GetTickCount() - startTickCount) > ssStatus.dwWaitHint) - break; - } - } - return ssStatus.dwCurrentState; -} - -/** - * Get the services that depend on @arg svc. All dependent service info - * is returned in an array of ENUM_SERVICE_STATUS structures via @arg deps. - * - * @retval The number of dependent services. - */ -DWORD SCM::getDependentServices(SC_HANDLE svc, - std::auto_ptr<ENUM_SERVICE_STATUS>& deps) -{ - DWORD bytesNeeded; - DWORD numEntries; - - // Pass a zero-length buffer to get the required buffer size. - if (::EnumDependentServices(svc, - SERVICE_ACTIVE, - 0, - 0, - &bytesNeeded, - &numEntries)) { - // If the Enum call succeeds, then there are no dependent - // services, so do nothing. - return 0; - } - - if (::GetLastError() != ERROR_MORE_DATA) - throw QPID_WINDOWS_ERROR((::GetLastError())); - - // Allocate a buffer for the dependencies. - deps.reset((LPENUM_SERVICE_STATUS)(new char[bytesNeeded])); - // Enumerate the dependencies. - if (!::EnumDependentServices(svc, - SERVICE_ACTIVE, - deps.get(), - bytesNeeded, - &bytesNeeded, - &numEntries)) - throw QPID_WINDOWS_ERROR((::GetLastError())); - return numEntries; -} - -} } // namespace qpid::windows diff --git a/cpp/src/qpid/sys/windows/SCM.h b/cpp/src/qpid/sys/windows/SCM.h deleted file mode 100644 index 8e94ef83c7..0000000000 --- a/cpp/src/qpid/sys/windows/SCM.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef WINDOWS_SCM_H -#define WINDOWS_SCM_H - -/* - * - * 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 <memory> -#include <string> -using std::string; - -#ifdef UNICODE -#undef UNICODE -#endif - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include <windows.h> - -#include "qpid/CommonImportExport.h" - -namespace qpid { -namespace windows { - -/** - * @class SCM - * - * Access the Windows Service Control Manager. - */ -class SCM -{ -public: - QPID_COMMON_EXTERN SCM(); - QPID_COMMON_EXTERN ~SCM(); - - /** - * Install this executable as a service - * - * @param serviceName The name of the service - * @param serviceDesc Description of the service's purpose - * @param args The argument list to pass into the service - * @param startType The start type: SERVICE_DEMAND_START, - * SERVICE_AUTO_START, SERVICE_DISABLED - * @param account If not empty, the account name to install this - * service under - * @param password If not empty, the account password to install this - * service with - * @param depends If not empty, a comma delimited list of services - * that must start before this one - */ - QPID_COMMON_EXTERN void install(const string& serviceName, - const string& serviceDesc, - const string& args, - DWORD startType = SERVICE_DEMAND_START, - const string& account = "NT AUTHORITY\\LocalSystem", - const string& password = "", - const string& depends = ""); - - /** - * Uninstall this executable as a service - * - * @param serviceName the name of the service - */ - QPID_COMMON_EXTERN void uninstall(const string& serviceName); - - /** - * Start the specified service - * - * @param serviceName the name of the service - */ - QPID_COMMON_EXTERN void start(const string& serviceName); - - /** - * Stop the specified service - * - * @param serviceName the name of the service - */ - QPID_COMMON_EXTERN void stop(const string &serviceName); - -private: - SC_HANDLE scmHandle; - - void openSvcManager(); - DWORD waitForStateChangeFrom(SC_HANDLE svc, DWORD originalState); - DWORD getDependentServices(SC_HANDLE svc, - std::auto_ptr<ENUM_SERVICE_STATUS>& deps); - -}; - -}} // namespace qpid::windows - -#endif /* #ifndef WINDOWS_SCM_H */ diff --git a/cpp/src/qpid/sys/windows/Shlib.cpp b/cpp/src/qpid/sys/windows/Shlib.cpp index ba18747eb4..38027de93f 100644 --- a/cpp/src/qpid/sys/windows/Shlib.cpp +++ b/cpp/src/qpid/sys/windows/Shlib.cpp @@ -44,8 +44,7 @@ void Shlib::unload() { } void* Shlib::getSymbol(const char* name) { - // Double cast avoids warning about casting function pointer to object - void *sym = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(GetProcAddress(static_cast<HMODULE>(handle), name))); + void* sym = GetProcAddress(static_cast<HMODULE>(handle), name); if (sym == NULL) throw QPID_WINDOWS_ERROR(GetLastError()); return sym; diff --git a/cpp/src/qpid/sys/windows/Socket.cpp b/cpp/src/qpid/sys/windows/Socket.cpp index 1fa4768329..11fb8b4133 100644..100755 --- a/cpp/src/qpid/sys/windows/Socket.cpp +++ b/cpp/src/qpid/sys/windows/Socket.cpp @@ -20,18 +20,19 @@ */ #include "qpid/sys/Socket.h" - #include "qpid/sys/SocketAddress.h" -#include "qpid/sys/windows/check.h" #include "qpid/sys/windows/IoHandlePrivate.h" +#include "qpid/sys/windows/check.h" +#include "qpid/sys/Time.h" -// Ensure we get all of winsock2.h -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif +#include <cstdlib> +#include <string.h> #include <winsock2.h> +#include <boost/format.hpp> +#include <boost/lexical_cast.hpp> + // Need to initialize WinSock. Ideally, this would be a singleton or embedded // in some one-time initialization function. I tried boost singleton and could // not get it to compile (and others located in google had the same problem). @@ -83,30 +84,53 @@ namespace sys { namespace { -std::string getName(SOCKET fd, bool local) +std::string getName(SOCKET fd, bool local, bool includeService = false) { - ::sockaddr_storage name_s; // big enough for any socket address - ::sockaddr* name = (::sockaddr*)&name_s; - ::socklen_t namelen = sizeof(name_s); - + sockaddr_in name; // big enough for any socket address + socklen_t namelen = sizeof(name); if (local) { - QPID_WINSOCK_CHECK(::getsockname(fd, name, &namelen)); + QPID_WINSOCK_CHECK(::getsockname(fd, (sockaddr*)&name, &namelen)); } else { - QPID_WINSOCK_CHECK(::getpeername(fd, name, &namelen)); + QPID_WINSOCK_CHECK(::getpeername(fd, (sockaddr*)&name, &namelen)); } - return SocketAddress::asString(name, namelen); + char servName[NI_MAXSERV]; + char dispName[NI_MAXHOST]; + if (includeService) { + if (int rc = ::getnameinfo((sockaddr*)&name, namelen, + dispName, sizeof(dispName), + servName, sizeof(servName), + NI_NUMERICHOST | NI_NUMERICSERV) != 0) + throw qpid::Exception(QPID_MSG(gai_strerror(rc))); + return std::string(dispName) + ":" + std::string(servName); + } else { + if (int rc = ::getnameinfo((sockaddr*)&name, namelen, + dispName, sizeof(dispName), + 0, 0, + NI_NUMERICHOST) != 0) + throw qpid::Exception(QPID_MSG(gai_strerror(rc))); + return dispName; + } } -uint16_t getLocalPort(int fd) +std::string getService(SOCKET fd, bool local) { - ::sockaddr_storage name_s; // big enough for any socket address - ::sockaddr* name = (::sockaddr*)&name_s; - ::socklen_t namelen = sizeof(name_s); - - QPID_WINSOCK_CHECK(::getsockname(fd, name, &namelen)); + sockaddr_in name; // big enough for any socket address + socklen_t namelen = sizeof(name); + + if (local) { + QPID_WINSOCK_CHECK(::getsockname(fd, (sockaddr*)&name, &namelen)); + } else { + QPID_WINSOCK_CHECK(::getpeername(fd, (sockaddr*)&name, &namelen)); + } - return SocketAddress::getPort(name); + char servName[NI_MAXSERV]; + if (int rc = ::getnameinfo((sockaddr*)&name, namelen, + 0, 0, + servName, sizeof(servName), + NI_NUMERICHOST | NI_NUMERICSERV) != 0) + throw qpid::Exception(QPID_MSG(gai_strerror(rc))); + return servName; } } // namespace @@ -114,7 +138,13 @@ Socket::Socket() : IOHandle(new IOHandlePrivate), nonblocking(false), nodelay(false) -{} +{ + SOCKET& socket = impl->fd; + if (socket != INVALID_SOCKET) Socket::close(); + SOCKET s = ::socket (PF_INET, SOCK_STREAM, 0); + if (s == INVALID_SOCKET) throw QPID_WINDOWS_ERROR(WSAGetLastError()); + socket = s; +} Socket::Socket(IOHandlePrivate* h) : IOHandle(h), @@ -122,7 +152,8 @@ Socket::Socket(IOHandlePrivate* h) : nodelay(false) {} -void Socket::createSocket(const SocketAddress& sa) const +void +Socket::createSocket(const SocketAddress& sa) const { SOCKET& socket = impl->fd; if (socket != INVALID_SOCKET) Socket::close(); @@ -137,24 +168,24 @@ void Socket::createSocket(const SocketAddress& sa) const if (nonblocking) setNonblocking(); if (nodelay) setTcpNoDelay(); } catch (std::exception&) { - ::closesocket(s); + closesocket(s); socket = INVALID_SOCKET; throw; } } -Socket* Socket::createSameTypeSocket() const { - SOCKET& socket = impl->fd; - // Socket currently has no actual socket attached - if (socket == INVALID_SOCKET) - return new Socket; - - ::sockaddr_storage sa; - ::socklen_t salen = sizeof(sa); - QPID_WINSOCK_CHECK(::getsockname(socket, (::sockaddr*)&sa, &salen)); - SOCKET s = ::socket(sa.ss_family, SOCK_STREAM, 0); // Currently only work with SOCK_STREAM - if (s == INVALID_SOCKET) throw QPID_WINDOWS_ERROR(WSAGetLastError()); - return new Socket(new IOHandlePrivate(s)); +void Socket::setTimeout(const Duration& interval) const +{ + const SOCKET& socket = impl->fd; + int64_t nanosecs = interval; + nanosecs /= (1000 * 1000); // nsecs -> usec -> msec + int msec = 0; + if (nanosecs > std::numeric_limits<int>::max()) + msec = std::numeric_limits<int>::max(); + else + msec = static_cast<int>(nanosecs); + setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&msec, sizeof(msec)); + setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&msec, sizeof(msec)); } void Socket::setNonblocking() const { @@ -162,25 +193,30 @@ void Socket::setNonblocking() const { QPID_WINSOCK_CHECK(ioctlsocket(impl->fd, FIONBIO, &nonblock)); } -void Socket::connect(const std::string& host, const std::string& port) const +void Socket::connect(const std::string& host, uint16_t port) const { - SocketAddress sa(host, port); + SocketAddress sa(host, boost::lexical_cast<std::string>(port)); connect(sa); } void Socket::connect(const SocketAddress& addr) const { - peername = addr.asString(false); - - createSocket(addr); - const SOCKET& socket = impl->fd; - int err; + const addrinfo *addrs = &(getAddrInfo(addr)); + int error = 0; WSASetLastError(0); - if ((::connect(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) != 0) && - ((err = ::WSAGetLastError()) != WSAEWOULDBLOCK)) - throw qpid::Exception(QPID_MSG(strError(err) << ": " << peername)); + while (addrs != 0) { + if ((::connect(socket, addrs->ai_addr, addrs->ai_addrlen) == 0) || + (WSAGetLastError() == WSAEWOULDBLOCK)) + break; + // Error... save this error code and see if there are other address + // to try before throwing the exception. + error = WSAGetLastError(); + addrs = addrs->ai_next; + } + if (error) + throw qpid::Exception(QPID_MSG(strError(error) << ": " << connectname)); } void @@ -211,26 +247,24 @@ int Socket::read(void *buf, size_t count) const return received; } -int Socket::listen(const std::string& host, const std::string& port, int backlog) const -{ - SocketAddress sa(host, port); - return listen(sa, backlog); -} - -int Socket::listen(const SocketAddress& addr, int backlog) const +int Socket::listen(uint16_t port, int backlog) const { - createSocket(addr); - const SOCKET& socket = impl->fd; BOOL yes=1; QPID_WINSOCK_CHECK(setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes))); - - if (::bind(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) == SOCKET_ERROR) - throw Exception(QPID_MSG("Can't bind to " << addr.asString() << ": " << strError(WSAGetLastError()))); + struct sockaddr_in name; + memset(&name, 0, sizeof(name)); + name.sin_family = AF_INET; + name.sin_port = htons(port); + name.sin_addr.s_addr = 0; + if (::bind(socket, (struct sockaddr*)&name, sizeof(name)) == SOCKET_ERROR) + throw Exception(QPID_MSG("Can't bind to port " << port << ": " << strError(WSAGetLastError()))); if (::listen(socket, backlog) == SOCKET_ERROR) - throw Exception(QPID_MSG("Can't listen on " <<addr.asString() << ": " << strError(WSAGetLastError()))); - - return getLocalPort(socket); + throw Exception(QPID_MSG("Can't listen on port " << port << ": " << strError(WSAGetLastError()))); + + socklen_t namelen = sizeof(name); + QPID_WINSOCK_CHECK(::getsockname(socket, (struct sockaddr*)&name, &namelen)); + return ntohs(name.sin_port); } Socket* Socket::accept() const @@ -243,20 +277,36 @@ Socket* Socket::accept() const else throw QPID_WINDOWS_ERROR(WSAGetLastError()); } +std::string Socket::getSockname() const +{ + return getName(impl->fd, true); +} + +std::string Socket::getPeername() const +{ + return getName(impl->fd, false); +} + std::string Socket::getPeerAddress() const { - if (peername.empty()) { - peername = getName(impl->fd, false); - } - return peername; + if (!connectname.empty()) + return std::string (connectname); + return getName(impl->fd, false, true); } std::string Socket::getLocalAddress() const { - if (localname.empty()) { - localname = getName(impl->fd, true); - } - return localname; + return getName(impl->fd, true, true); +} + +uint16_t Socket::getLocalPort() const +{ + return atoi(getService(impl->fd, true).c_str()); +} + +uint16_t Socket::getRemotePort() const +{ + return atoi(getService(impl->fd, true).c_str()); } int Socket::getError() const diff --git a/cpp/src/qpid/sys/windows/SocketAddress.cpp b/cpp/src/qpid/sys/windows/SocketAddress.cpp index 77bbf85810..501cff1297 100644 --- a/cpp/src/qpid/sys/windows/SocketAddress.cpp +++ b/cpp/src/qpid/sys/windows/SocketAddress.cpp @@ -21,13 +21,7 @@ #include "qpid/sys/SocketAddress.h" -#include "qpid/Exception.h" -#include "qpid/Msg.h" - -// Ensure we get all of winsock2.h -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif +#include "qpid/sys/windows/check.h" #include <winsock2.h> #include <ws2tcpip.h> @@ -41,111 +35,37 @@ SocketAddress::SocketAddress(const std::string& host0, const std::string& port0) port(port0), addrInfo(0) { -} - -SocketAddress::SocketAddress(const SocketAddress& sa) : - host(sa.host), - port(sa.port), - addrInfo(0) -{ -} - -SocketAddress& SocketAddress::operator=(const SocketAddress& sa) -{ - SocketAddress temp(sa); - - std::swap(temp, *this); - return *this; -} - -SocketAddress::~SocketAddress() -{ - if (addrInfo) { - ::freeaddrinfo(addrInfo); + ::addrinfo hints; + ::memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; // In order to allow AF_INET6 we'd have to change createTcp() as well + hints.ai_socktype = SOCK_STREAM; + + const char* node = 0; + if (host.empty()) { + hints.ai_flags |= AI_PASSIVE; + } else { + node = host.c_str(); } -} + const char* service = port.empty() ? "0" : port.c_str(); -std::string SocketAddress::asString(::sockaddr const * const addr, size_t addrlen) -{ - char servName[NI_MAXSERV]; - char dispName[NI_MAXHOST]; - if (int rc=::getnameinfo(addr, addrlen, - dispName, sizeof(dispName), - servName, sizeof(servName), - NI_NUMERICHOST | NI_NUMERICSERV) != 0) - throw qpid::Exception(QPID_MSG(gai_strerror(rc))); - std::string s; - switch (addr->sa_family) { - case AF_INET: s += dispName; break; - case AF_INET6: s += "["; s += dispName; s+= "]"; break; - default: throw Exception(QPID_MSG("Unexpected socket type")); - } - s += ":"; - s += servName; - return s; + int n = ::getaddrinfo(node, service, &hints, &addrInfo); + if (n != 0) + throw Exception(QPID_MSG("Cannot resolve " << host << ": " << ::gai_strerror(n))); } -uint16_t SocketAddress::getPort(::sockaddr const * const addr) +SocketAddress::~SocketAddress() { - switch (addr->sa_family) { - case AF_INET: return ntohs(((::sockaddr_in*)addr)->sin_port); - case AF_INET6: return ntohs(((::sockaddr_in6*)addr)->sin6_port); - default:throw Exception(QPID_MSG("Unexpected socket type")); - } + ::freeaddrinfo(addrInfo); } -std::string SocketAddress::asString(bool numeric) const +std::string SocketAddress::asString() const { - if (!numeric) - return host + ":" + port; - // Canonicalise into numeric id - const ::addrinfo& ai = getAddrInfo(*this); - - return asString(ai.ai_addr, ai.ai_addrlen); -} - -bool SocketAddress::nextAddress() { - bool r = currentAddrInfo->ai_next != 0; - if (r) - currentAddrInfo = currentAddrInfo->ai_next; - return r; -} - -void SocketAddress::setAddrInfoPort(uint16_t port) { - if (!currentAddrInfo) return; - - ::addrinfo& ai = *currentAddrInfo; - switch (ai.ai_family) { - case AF_INET: ((::sockaddr_in*)ai.ai_addr)->sin_port = htons(port); return; - case AF_INET6:((::sockaddr_in6*)ai.ai_addr)->sin6_port = htons(port); return; - default: throw Exception(QPID_MSG("Unexpected socket type")); - } + return host + ":" + port; } const ::addrinfo& getAddrInfo(const SocketAddress& sa) { - if (!sa.addrInfo) { - ::addrinfo hints; - ::memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_ADDRCONFIG; // Only use protocols that we have configured interfaces for - hints.ai_family = AF_UNSPEC; // Allow both IPv4 and IPv6 - hints.ai_socktype = SOCK_STREAM; - - const char* node = 0; - if (sa.host.empty()) { - hints.ai_flags |= AI_PASSIVE; - } else { - node = sa.host.c_str(); - } - const char* service = sa.port.empty() ? "0" : sa.port.c_str(); - - int n = ::getaddrinfo(node, service, &hints, &sa.addrInfo); - if (n != 0) - throw Exception(QPID_MSG("Cannot resolve " << sa.asString(false) << ": " << ::gai_strerror(n))); - sa.currentAddrInfo = sa.addrInfo; - } - - return *sa.currentAddrInfo; + return *sa.addrInfo; } }} diff --git a/cpp/src/qpid/sys/windows/SslAsynchIO.h b/cpp/src/qpid/sys/windows/SslAsynchIO.h index edec081ced..3cdf2c8f08 100644 --- a/cpp/src/qpid/sys/windows/SslAsynchIO.h +++ b/cpp/src/qpid/sys/windows/SslAsynchIO.h @@ -39,6 +39,9 @@ namespace qpid { namespace sys { namespace windows { +class Socket; +class Poller; + /* * SSL/Schannel shim between the frame-handling and AsynchIO layers. * SslAsynchIO creates a regular AsynchIO object to handle I/O and this class diff --git a/cpp/src/qpid/sys/windows/StrError.cpp b/cpp/src/qpid/sys/windows/StrError.cpp index 546d399d16..9c1bfcd79c 100755 --- a/cpp/src/qpid/sys/windows/StrError.cpp +++ b/cpp/src/qpid/sys/windows/StrError.cpp @@ -30,7 +30,6 @@ namespace sys { std::string strError(int err) { const size_t bufsize = 512; char buf[bufsize]; - buf[0] = 0; if (0 == FormatMessage (FORMAT_MESSAGE_MAX_WIDTH_MASK | FORMAT_MESSAGE_FROM_SYSTEM, 0, @@ -40,11 +39,7 @@ std::string strError(int err) { bufsize, 0)) { -#ifdef _MSC_VER - strerror_s(buf, bufsize, err); -#else - return std::string(strerror(err)); -#endif + strerror_s (buf, bufsize, err); } return std::string(buf); } diff --git a/cpp/src/qpid/sys/windows/Thread.cpp b/cpp/src/qpid/sys/windows/Thread.cpp index 23b0033be4..583a9613a3 100755 --- a/cpp/src/qpid/sys/windows/Thread.cpp +++ b/cpp/src/qpid/sys/windows/Thread.cpp @@ -19,11 +19,6 @@ * */ -// Ensure definition of OpenThread in mingw -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif - #include "qpid/sys/Thread.h" #include "qpid/sys/Runnable.h" #include "qpid/sys/windows/check.h" @@ -31,204 +26,50 @@ #include <process.h> #include <windows.h> -/* - * This implementation distinguishes between two types of thread: Qpid - * threads (based on qpid::sys::Runnable) and the rest. It provides a - * join() that will not deadlock against the Windows loader lock for - * Qpid threads. - * - * System thread identifiers are unique per Windows thread; thread - * handles are not. Thread identifiers can be recycled, but keeping a - * handle open against the thread prevents recycling as long as - * shared_ptr references to a ThreadPrivate structure remain. - * - * There is a 1-1 relationship between Qpid threads and their - * ThreadPrivate structure. Non-Qpid threads do not need to find the - * qpidThreadDone handle, so there may be a 1-many relationship for - * them. - * - * TLS storage is used for a lockless solution for static library - * builds. The special case of LoadLibrary/FreeLibrary requires - * additional synchronization variables and resource cleanup in - * DllMain. _DLL marks the dynamic case. - */ +namespace { +unsigned __stdcall runRunnable(void* p) +{ + static_cast<qpid::sys::Runnable*>(p)->run(); + _endthreadex(0); + return 0; +} +} namespace qpid { namespace sys { class ThreadPrivate { -public: friend class Thread; - friend unsigned __stdcall runThreadPrivate(void*); - typedef boost::shared_ptr<ThreadPrivate> shared_ptr; - ~ThreadPrivate(); -private: - unsigned threadId; HANDLE threadHandle; - HANDLE initCompleted; - HANDLE qpidThreadDone; - Runnable* runnable; - shared_ptr keepAlive; - - ThreadPrivate() : threadId(GetCurrentThreadId()), initCompleted(NULL), - qpidThreadDone(NULL), runnable(NULL) { - threadHandle = OpenThread (SYNCHRONIZE, FALSE, threadId); - QPID_WINDOWS_CHECK_CRT_NZ(threadHandle); - } - - ThreadPrivate(Runnable* r) : threadHandle(NULL), initCompleted(NULL), - qpidThreadDone(NULL), runnable(r) {} - - void start(shared_ptr& p); - static shared_ptr createThread(Runnable* r); -}; - -}} // namespace qpid::sys - - -namespace { -using namespace qpid::sys; - -#ifdef _DLL -class ScopedCriticalSection -{ - public: - ScopedCriticalSection(CRITICAL_SECTION& cs) : criticalSection(cs) { EnterCriticalSection(&criticalSection); } - ~ScopedCriticalSection() { LeaveCriticalSection(&criticalSection); } - private: - CRITICAL_SECTION& criticalSection; -}; - -CRITICAL_SECTION threadLock; -long runningThreads = 0; -HANDLE threadsDone; -bool terminating = false; -#endif - - -DWORD volatile tlsIndex = TLS_OUT_OF_INDEXES; - -DWORD getTlsIndex() { - if (tlsIndex != TLS_OUT_OF_INDEXES) - return tlsIndex; // already set - - DWORD trialIndex = TlsAlloc(); - QPID_WINDOWS_CHECK_NOT(trialIndex, TLS_OUT_OF_INDEXES); // No OS resource + unsigned threadId; - // only one thread gets to set the value - DWORD actualIndex = (DWORD) InterlockedCompareExchange((LONG volatile *) &tlsIndex, (LONG) trialIndex, (LONG) TLS_OUT_OF_INDEXES); - if (actualIndex == TLS_OUT_OF_INDEXES) - return trialIndex; // we won the race - else { - TlsFree(trialIndex); - return actualIndex; + ThreadPrivate(Runnable* runnable) { + uintptr_t h = _beginthreadex(0, + 0, + runRunnable, + runnable, + 0, + &threadId); + QPID_WINDOWS_CHECK_CRT_NZ(h); + threadHandle = reinterpret_cast<HANDLE>(h); } -} - -} // namespace - -namespace qpid { -namespace sys { - -unsigned __stdcall runThreadPrivate(void* p) -{ - ThreadPrivate* threadPrivate = static_cast<ThreadPrivate*>(p); - TlsSetValue(getTlsIndex(), threadPrivate); - - WaitForSingleObject (threadPrivate->initCompleted, INFINITE); - CloseHandle (threadPrivate->initCompleted); - threadPrivate->initCompleted = NULL; - - try { - threadPrivate->runnable->run(); - } catch (...) { - // not our concern - } - - SetEvent (threadPrivate->qpidThreadDone); // allow join() - threadPrivate->keepAlive.reset(); // may run ThreadPrivate destructor - -#ifdef _DLL - { - ScopedCriticalSection l(threadLock); - if (--runningThreads == 0) - SetEvent(threadsDone); - } -#endif - return 0; -} - - -ThreadPrivate::shared_ptr ThreadPrivate::createThread(Runnable* runnable) { - ThreadPrivate::shared_ptr tp(new ThreadPrivate(runnable)); - tp->start(tp); - return tp; -} - -void ThreadPrivate::start(ThreadPrivate::shared_ptr& tp) { - getTlsIndex(); // fail here if OS problem, not in new thread - - initCompleted = CreateEvent (NULL, TRUE, FALSE, NULL); - QPID_WINDOWS_CHECK_CRT_NZ(initCompleted); - qpidThreadDone = CreateEvent (NULL, TRUE, FALSE, NULL); - QPID_WINDOWS_CHECK_CRT_NZ(qpidThreadDone); - -#ifdef _DLL - { - ScopedCriticalSection l(threadLock); - if (terminating) - throw qpid::Exception(QPID_MSG("creating thread after exit/FreeLibrary")); - runningThreads++; - } -#endif - - uintptr_t h = _beginthreadex(0, - 0, - runThreadPrivate, - (void *)this, - 0, - &threadId); - -#ifdef _DLL - if (h == NULL) { - ScopedCriticalSection l(threadLock); - if (--runningThreads == 0) - SetEvent(threadsDone); - } -#endif - - QPID_WINDOWS_CHECK_CRT_NZ(h); - - // Success - keepAlive = tp; - threadHandle = reinterpret_cast<HANDLE>(h); - SetEvent (initCompleted); -} - -ThreadPrivate::~ThreadPrivate() { - if (threadHandle) - CloseHandle (threadHandle); - if (initCompleted) - CloseHandle (initCompleted); - if (qpidThreadDone) - CloseHandle (qpidThreadDone); -} - + + ThreadPrivate() + : threadHandle(GetCurrentThread()), threadId(GetCurrentThreadId()) {} +}; Thread::Thread() {} -Thread::Thread(Runnable* runnable) : impl(ThreadPrivate::createThread(runnable)) {} +Thread::Thread(Runnable* runnable) : impl(new ThreadPrivate(runnable)) {} -Thread::Thread(Runnable& runnable) : impl(ThreadPrivate::createThread(&runnable)) {} +Thread::Thread(Runnable& runnable) : impl(new ThreadPrivate(&runnable)) {} Thread::operator bool() { return impl; } bool Thread::operator==(const Thread& t) const { - if (!impl || !t.impl) - return false; return impl->threadId == t.impl->threadId; } @@ -238,17 +79,10 @@ bool Thread::operator!=(const Thread& t) const { void Thread::join() { if (impl) { - DWORD status; - if (impl->runnable) { - HANDLE handles[2] = {impl->qpidThreadDone, impl->threadHandle}; - // wait for either. threadHandle not signalled if loader - // lock held (FreeLibrary). qpidThreadDone not signalled - // if thread terminated by exit(). - status = WaitForMultipleObjects (2, handles, false, INFINITE); - } - else - status = WaitForSingleObject (impl->threadHandle, INFINITE); + DWORD status = WaitForSingleObject (impl->threadHandle, INFINITE); QPID_WINDOWS_CHECK_NOT(status, WAIT_FAILED); + CloseHandle (impl->threadHandle); + impl->threadHandle = 0; } } @@ -258,70 +92,9 @@ unsigned long Thread::logId() { /* static */ Thread Thread::current() { - ThreadPrivate* tlsValue = (ThreadPrivate *) TlsGetValue(getTlsIndex()); Thread t; - if (tlsValue != NULL) { - // called from within Runnable->run(), so keepAlive has positive use count - t.impl = tlsValue->keepAlive; - } - else - t.impl.reset(new ThreadPrivate()); + t.impl.reset(new ThreadPrivate()); return t; } -}} // namespace qpid::sys - - -#ifdef _DLL - -// DllMain: called possibly many times in a process lifetime if dll -// loaded and freed repeatedly . Be mindful of Windows loader lock -// and other DllMain restrictions. - -BOOL APIENTRY DllMain(HMODULE hm, DWORD reason, LPVOID reserved) { - switch (reason) { - case DLL_PROCESS_ATTACH: - InitializeCriticalSection(&threadLock); - threadsDone = CreateEvent(NULL, TRUE, FALSE, NULL); - break; - - case DLL_PROCESS_DETACH: - terminating = true; - 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. - return TRUE; - } - else { - // FreeLibrary(): threads are still running and we are - // 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. - while (1) { - { - ScopedCriticalSection l(threadLock); - if (runningThreads == 0) - break; - ResetEvent(threadsDone); - } - WaitForSingleObject(threadsDone, INFINITE); - } - if (tlsIndex != TLS_OUT_OF_INDEXES) - TlsFree(getTlsIndex()); - CloseHandle(threadsDone); - DeleteCriticalSection(&threadLock); - } - break; - - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - break; - } - return TRUE; -} - -#endif +}} /* qpid::sys */ diff --git a/cpp/src/qpid/sys/windows/Time.cpp b/cpp/src/qpid/sys/windows/Time.cpp index 25c50819cd..16d09fcdc0 100644 --- a/cpp/src/qpid/sys/windows/Time.cpp +++ b/cpp/src/qpid/sys/windows/Time.cpp @@ -27,17 +27,6 @@ using namespace boost::posix_time; -namespace { - -// High-res timing support. This will display times since program start, -// more or less. Keep track of the start value and the conversion factor to -// seconds. -bool timeInitialized = false; -LARGE_INTEGER start; -double freq = 1.0; - -} - namespace qpid { namespace sys { @@ -102,35 +91,10 @@ void outputFormattedNow(std::ostream& o) { char time_string[100]; ::time( &rawtime ); -#ifdef _MSC_VER ::localtime_s(&timeinfo, &rawtime); -#else - timeinfo = *(::localtime(&rawtime)); -#endif ::strftime(time_string, 100, "%Y-%m-%d %H:%M:%S", &timeinfo); o << time_string << " "; } - -void outputHiresNow(std::ostream& o) { - if (!timeInitialized) { - start.QuadPart = 0; - LARGE_INTEGER iFreq; - iFreq.QuadPart = 1; - QueryPerformanceCounter(&start); - QueryPerformanceFrequency(&iFreq); - freq = static_cast<double>(iFreq.QuadPart); - timeInitialized = true; - } - LARGE_INTEGER iNow; - iNow.QuadPart = 0; - QueryPerformanceCounter(&iNow); - iNow.QuadPart -= start.QuadPart; - if (iNow.QuadPart < 0) - iNow.QuadPart = 0; - double now = static_cast<double>(iNow.QuadPart); - now /= freq; // now is seconds after this - o << std::fixed << std::setprecision(8) << std::setw(16) << std::setfill('0') << now << "s "; -} }} diff --git a/cpp/src/qpid/sys/windows/mingw32_compat.h b/cpp/src/qpid/sys/windows/mingw32_compat.h deleted file mode 100644 index 51f613cc25..0000000000 --- a/cpp/src/qpid/sys/windows/mingw32_compat.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _sys_windows_mingw32_compat -#define _sys_windows_mingw32_compat -/* - * - * 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. - * - */ - -#ifdef WIN32 -#ifndef _MSC_VER - -// -// The following definitions for extension function GUIDs and signatures are taken from -// MswSock.h in the Windows32 SDK. These rightfully belong in the mingw32 version of -// mswsock.h, but are not included presently. -// - -#define WSAID_ACCEPTEX {0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} -typedef BOOL (PASCAL *LPFN_ACCEPTEX)(SOCKET,SOCKET,PVOID,DWORD,DWORD,DWORD,LPDWORD,LPOVERLAPPED); - -#endif -#endif - -#endif diff --git a/cpp/src/qpid/sys/windows/uuid.cpp b/cpp/src/qpid/sys/windows/uuid.cpp index 3316ecbc00..b5360622dc 100644 --- a/cpp/src/qpid/sys/windows/uuid.cpp +++ b/cpp/src/qpid/sys/windows/uuid.cpp @@ -19,7 +19,7 @@ * */ -#include <rpc.h> +#include <Rpc.h> #ifdef uuid_t /* Done in rpcdce.h */ # undef uuid_t #endif @@ -52,11 +52,7 @@ int uuid_parse (const char *in, uuid_t uu) { void uuid_unparse (const uuid_t uu, char *out) { unsigned char *formatted; if (UuidToString((UUID*)uu, &formatted) == RPC_S_OK) { -#ifdef _MSC_VER strncpy_s (out, 36+1, (char*)formatted, _TRUNCATE); -#else - strncpy (out, (char*)formatted, 36+1); -#endif RpcStringFree(&formatted); } } |
