summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2018-03-01 14:00:39 +0100
committerBenoit Foucher <benoit@zeroc.com>2018-03-01 14:00:39 +0100
commit6a53b1575ed0f855108abc5184744c2529c151ae (patch)
tree6e9188775461599b5c83890e226da62e5f255a7f
parentFixed JS test suite hang (ICE-8696) (diff)
downloadice-6a53b1575ed0f855108abc5184744c2529c151ae.tar.bz2
ice-6a53b1575ed0f855108abc5184744c2529c151ae.tar.xz
ice-6a53b1575ed0f855108abc5184744c2529c151ae.zip
Fixed UWP transport to cancel read/write operations on close (ICE-8686)
-rwxr-xr-xcpp/src/Ice/Network.cpp2
-rwxr-xr-xcpp/src/Ice/Network.h11
-rwxr-xr-xcpp/src/Ice/StreamSocket.cpp18
-rw-r--r--cpp/src/Ice/ThreadPool.cpp10
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);