diff options
author | Benoit Foucher <benoit@zeroc.com> | 2018-03-01 14:00:39 +0100 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2018-03-01 14:00:39 +0100 |
commit | 6a53b1575ed0f855108abc5184744c2529c151ae (patch) | |
tree | 6e9188775461599b5c83890e226da62e5f255a7f | |
parent | Fixed JS test suite hang (ICE-8696) (diff) | |
download | ice-6a53b1575ed0f855108abc5184744c2529c151ae.tar.bz2 ice-6a53b1575ed0f855108abc5184744c2529c151ae.tar.xz ice-6a53b1575ed0f855108abc5184744c2529c151ae.zip |
Fixed UWP transport to cancel read/write operations on close (ICE-8686)
-rwxr-xr-x | cpp/src/Ice/Network.cpp | 2 | ||||
-rwxr-xr-x | cpp/src/Ice/Network.h | 11 | ||||
-rwxr-xr-x | cpp/src/Ice/StreamSocket.cpp | 18 | ||||
-rw-r--r-- | cpp/src/Ice/ThreadPool.cpp | 10 |
4 files changed, 23 insertions, 18 deletions
diff --git a/cpp/src/Ice/Network.cpp b/cpp/src/Ice/Network.cpp index bcfa9e8b54d..9b08d7b9fc7 100755 --- a/cpp/src/Ice/Network.cpp +++ b/cpp/src/Ice/Network.cpp @@ -875,6 +875,7 @@ IceInternal::NativeInfo::queueAction(SocketOperation op, IAsyncAction^ action, b // this->queueActionCompleted(op, asyncInfo, info, status); }); + asyncInfo->operation = action; } } @@ -928,6 +929,7 @@ IceInternal::NativeInfo::queueOperation(SocketOperation op, IAsyncOperation<unsi }); } operation->Completed = info->completedHandler; + info->operation = operation; } } diff --git a/cpp/src/Ice/Network.h b/cpp/src/Ice/Network.h index 2fad0c77d1c..d0ea1474f7d 100755 --- a/cpp/src/Ice/Network.h +++ b/cpp/src/Ice/Network.h @@ -152,16 +152,6 @@ enum SocketOperation }; // -// On UWP, wait only for read to return, on IOCP/Win32 wait for -// both pending read and write operations to complete (#ICE-6695). -// -#if defined(ICE_OS_UWP) -const int SocketOperationWaitForClose = 1; -#elif defined(ICE_USE_IOCP) -const int SocketOperationWaitForClose = 3; -#endif - -// // AsyncInfo struct for Windows IOCP or UWP holds the result of // asynchronous operations after it completed. // @@ -180,6 +170,7 @@ struct ICE_API AsyncInfo : WSAOVERLAPPED struct ICE_API AsyncInfo { Windows::Foundation::AsyncOperationCompletedHandler<unsigned int>^ completedHandler; + Windows::Foundation::IAsyncInfo^ operation; int count; int error; }; diff --git a/cpp/src/Ice/StreamSocket.cpp b/cpp/src/Ice/StreamSocket.cpp index 274f52000f2..dd6c1a66546 100755 --- a/cpp/src/Ice/StreamSocket.cpp +++ b/cpp/src/Ice/StreamSocket.cpp @@ -18,7 +18,6 @@ using namespace IceInternal; #include <Ice/Properties.h> using namespace Platform; using namespace Windows::Foundation; - #endif StreamSocket::StreamSocket(const ProtocolInstancePtr& instance, @@ -509,8 +508,9 @@ StreamSocket::startWrite(Buffer& buf) try { queueAction(SocketOperationConnect, - safe_cast<Windows::Networking::Sockets::StreamSocket^>(_fd)->ConnectAsync(addr.host, addr.port, - Windows::Networking::Sockets::SocketProtectionLevel::PlainSocket), true); + safe_cast<Windows::Networking::Sockets::StreamSocket^>(_fd)->ConnectAsync( + addr.host, addr.port, + Windows::Networking::Sockets::SocketProtectionLevel::PlainSocket), true); } catch(Platform::Exception^ ex) { @@ -548,6 +548,7 @@ StreamSocket::startWrite(Buffer& buf) void StreamSocket::finishWrite(Buffer& buf) { + _write.operation = nullptr; // Must be cleared with the connection lock held if(_fd == INVALID_SOCKET || (_state < StateConnected && _state != StateProxyWrite)) { return; @@ -579,6 +580,7 @@ StreamSocket::startRead(Buffer& buf) void StreamSocket::finishRead(Buffer& buf) { + _read.operation = nullptr; // Must be cleared with the connection lock held if(_fd == INVALID_SOCKET) { return; @@ -615,6 +617,16 @@ StreamSocket::close() assert(_fd != INVALID_SOCKET); try { +#if defined(ICE_OS_UWP) + if(_read.operation) + { + _read.operation->Cancel(); + } + if(_write.operation) + { + _write.operation->Cancel(); + } +#endif closeSocket(_fd); _fd = INVALID_SOCKET; } diff --git a/cpp/src/Ice/ThreadPool.cpp b/cpp/src/Ice/ThreadPool.cpp index e1d5165c31f..6d514a48891 100644 --- a/cpp/src/Ice/ThreadPool.cpp +++ b/cpp/src/Ice/ThreadPool.cpp @@ -507,7 +507,7 @@ IceInternal::ThreadPool::finish(const EventHandlerPtr& handler, bool closeNow) return closeNow; #else // If there are no pending asynchronous operations, we can call finish on the handler now. - if(!(handler->_pending & SocketOperationWaitForClose)) + if(!handler->_pending) { _workQueue->queue(new FinishedWorkItem(handler, false)); _selector.finish(handler.get()); @@ -983,7 +983,7 @@ IceInternal::ThreadPool::startMessage(ThreadPoolCurrent& current) if(!current._handler->finishAsync(current.operation)) // Returns false if the handler is finished. { current._handler->_pending = static_cast<SocketOperation>(current._handler->_pending & ~current.operation); - if(!(current._handler->_pending & SocketOperationWaitForClose) && current._handler->_finish) + if(!current._handler->_pending && current._handler->_finish) { Lock sync(*this); _workQueue->queue(new FinishedWorkItem(current._handler, false)); @@ -1010,7 +1010,7 @@ IceInternal::ThreadPool::startMessage(ThreadPoolCurrent& current) else if(!current._handler->startAsync(current.operation)) { current._handler->_pending = static_cast<SocketOperation>(current._handler->_pending & ~current.operation); - if(!(current._handler->_pending & SocketOperationWaitForClose) && current._handler->_finish) + if(!current._handler->_pending && current._handler->_finish) { Lock sync(*this); _workQueue->queue(new FinishedWorkItem(current._handler, false)); @@ -1034,7 +1034,7 @@ IceInternal::ThreadPool::startMessage(ThreadPoolCurrent& current) else { current._handler->_pending = static_cast<SocketOperation>(current._handler->_pending & ~current.operation); - if(!(current._handler->_pending & SocketOperationWaitForClose) && current._handler->_finish) + if(!current._handler->_pending && current._handler->_finish) { Lock sync(*this); _workQueue->queue(new FinishedWorkItem(current._handler, false)); @@ -1069,7 +1069,7 @@ IceInternal::ThreadPool::finishMessage(ThreadPoolCurrent& current) current._handler->_pending = static_cast<SocketOperation>(current._handler->_pending & ~current.operation); } - if(!(current._handler->_pending & SocketOperationWaitForClose) && current._handler->_finish) + if(!current._handler->_pending && current._handler->_finish) { // There are no more pending async operations, it's time to call finish. Lock sync(*this); |