From 1d32ae18f5c9fa18560ee9cec9b921bd96b4bf3e Mon Sep 17 00:00:00 2001 From: Jose Date: Thu, 22 Feb 2018 14:00:25 +0100 Subject: Fix UWP async operation status checks --- cpp/src/Ice/Network.cpp | 19 ++++++++++++++----- cpp/src/Ice/Network.h | 2 +- cpp/src/Ice/UdpTransceiver.cpp | 15 ++------------- 3 files changed, 17 insertions(+), 19 deletions(-) (limited to 'cpp/src') diff --git a/cpp/src/Ice/Network.cpp b/cpp/src/Ice/Network.cpp index 788704b50f4..bcfa9e8b54d 100755 --- a/cpp/src/Ice/Network.cpp +++ b/cpp/src/Ice/Network.cpp @@ -859,7 +859,7 @@ void IceInternal::NativeInfo::queueAction(SocketOperation op, IAsyncAction^ action, bool connect) { AsyncInfo* asyncInfo = getAsyncInfo(op); - if(checkIfErrorOrCompleted(op, action, connect)) + if(checkIfErrorOrCompleted(op, action, action->Status, connect)) { asyncInfo->count = 0; } @@ -898,11 +898,21 @@ void IceInternal::NativeInfo::queueOperation(SocketOperation op, IAsyncOperation^ operation) { AsyncInfo* info = getAsyncInfo(op); - if(checkIfErrorOrCompleted(op, operation)) + Windows::Foundation::AsyncStatus status = operation->Status; + if (status == Windows::Foundation::AsyncStatus::Completed) { + // + // NOTE: it's important to modify the count _before_ calling the completion handler + // since this might not always be called with the connection mutex but from a Windows + // thread pool thread if we chained multiple Async calls (GetGetOutputStreamAsync and + // StoreAsync for example, see the UDPTransceiver implementation). So we can't modify + // the AsyncInfo structure after calling the completed callback. + // info->count = static_cast(operation->GetResults()); + _completedHandler(op); + return; } - else + else if(!checkIfErrorOrCompleted(op, operation, status)) { if(!info->completedHandler) { @@ -952,7 +962,7 @@ IceInternal::NativeInfo::completed(SocketOperation operation) } bool -IceInternal::NativeInfo::checkIfErrorOrCompleted(SocketOperation op, IAsyncInfo^ info, bool connect) +IceInternal::NativeInfo::checkIfErrorOrCompleted(SocketOperation op, IAsyncInfo^ info, Windows::Foundation::AsyncStatus status, bool connect) { // // NOTE: It's important to only check for info->Status once as it @@ -963,7 +973,6 @@ IceInternal::NativeInfo::checkIfErrorOrCompleted(SocketOperation op, IAsyncInfo^ // error. A canceled async status can occur if there's a timeout // and the socket is closed. // - Windows::Foundation::AsyncStatus status = info->Status; if(status == Windows::Foundation::AsyncStatus::Completed) { _completedHandler(op); diff --git a/cpp/src/Ice/Network.h b/cpp/src/Ice/Network.h index 6057c68c076..2fad0c77d1c 100755 --- a/cpp/src/Ice/Network.h +++ b/cpp/src/Ice/Network.h @@ -250,7 +250,7 @@ protected: HANDLE _handle; ULONG_PTR _key; #elif defined(ICE_OS_UWP) - bool checkIfErrorOrCompleted(SocketOperation, Windows::Foundation::IAsyncInfo^, bool = false); + bool checkIfErrorOrCompleted(SocketOperation, Windows::Foundation::IAsyncInfo^, Windows::Foundation::AsyncStatus, bool = false); SocketOperationCompletedHandler^ _completedHandler; #else SOCKET _newFd; diff --git a/cpp/src/Ice/UdpTransceiver.cpp b/cpp/src/Ice/UdpTransceiver.cpp index b2c29a95676..64c2a756bc1 100755 --- a/cpp/src/Ice/UdpTransceiver.cpp +++ b/cpp/src/Ice/UdpTransceiver.cpp @@ -370,7 +370,7 @@ IceInternal::UdpTransceiver::startWrite(Buffer& buf) if(!multicast) { auto operation = safe_cast(_fd)->ConnectAsync(_addr.host, _addr.port); - if(!checkIfErrorOrCompleted(SocketOperationConnect, operation)) + if(!checkIfErrorOrCompleted(SocketOperationConnect, operation, operation->Status)) { operation->Completed = ref new AsyncActionCompletedHandler( [this] (IAsyncAction^ info, Windows::Foundation::AsyncStatus status) @@ -392,7 +392,7 @@ IceInternal::UdpTransceiver::startWrite(Buffer& buf) else { auto operation = safe_cast(_fd)->GetOutputStreamAsync(_addr.host, _addr.port); - if(!checkIfErrorOrCompleted(SocketOperationConnect, operation)) + if(!checkIfErrorOrCompleted(SocketOperationConnect, operation, operation->Status)) { operation->Completed = ref new AsyncOperationCompletedHandler( [=](IAsyncOperation^ info, Windows::Foundation::AsyncStatus status) @@ -550,17 +550,6 @@ IceInternal::UdpTransceiver::getOutputStreamCompleted(concurrency::taskWriteBytes(ref new Array(&*buf.i, static_cast(buf.b.size()))); DataWriterStoreOperation^ operation = writer->StoreAsync(); - if(operation->Status == Windows::Foundation::AsyncStatus::Completed) - { - // - // NOTE: unlike other methods, it's important to modify _write.count - // _before_ calling checkIfErrorOrCompleted since this isn't called - // with the connection mutex but from a Windows thread pool thread. - // So we can't modify the _write structure after calling the - // completed callback. - // - _write.count = operation->GetResults(); - } queueOperation(SocketOperationWrite, operation); } catch(Platform::Exception^ pex) -- cgit v1.2.3