summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorJose <jose@zeroc.com>2018-02-22 14:00:25 +0100
committerJose <jose@zeroc.com>2018-02-22 14:00:25 +0100
commit1d32ae18f5c9fa18560ee9cec9b921bd96b4bf3e (patch)
treee14937531f49cde31c16cc521d40e1cac025f804 /cpp/src
parentUWP crash if udp send completes after transceiver is close (diff)
downloadice-1d32ae18f5c9fa18560ee9cec9b921bd96b4bf3e.tar.bz2
ice-1d32ae18f5c9fa18560ee9cec9b921bd96b4bf3e.tar.xz
ice-1d32ae18f5c9fa18560ee9cec9b921bd96b4bf3e.zip
Fix UWP async operation status checks
Diffstat (limited to 'cpp/src')
-rwxr-xr-xcpp/src/Ice/Network.cpp19
-rwxr-xr-xcpp/src/Ice/Network.h2
-rwxr-xr-xcpp/src/Ice/UdpTransceiver.cpp15
3 files changed, 17 insertions, 19 deletions
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<unsigned int>^ 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<int>(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<DatagramSocket^>(_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<DatagramSocket^>(_fd)->GetOutputStreamAsync(_addr.host, _addr.port);
- if(!checkIfErrorOrCompleted(SocketOperationConnect, operation))
+ if(!checkIfErrorOrCompleted(SocketOperationConnect, operation, operation->Status))
{
operation->Completed = ref new AsyncOperationCompletedHandler<IOutputStream^>(
[=](IAsyncOperation<IOutputStream^>^ info, Windows::Foundation::AsyncStatus status)
@@ -550,17 +550,6 @@ IceInternal::UdpTransceiver::getOutputStreamCompleted(concurrency::task<IOutputS
DataWriter^ writer = ref new DataWriter(task.get());
writer->WriteBytes(ref new Array<unsigned char>(&*buf.i, static_cast<int>(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)