Answered by:
StreamSocket with SSL causes crash when using PPL Task in C++

Question
-
I make a sample that is composed of a SocketStress app in CSharp and a Windows Runtime Component WRC in C++ to show this problem. WRC contains class SocketWrapper that implements a wrapper for StreamSocket with SSL. The SocketStress sample repeatedly calls into WRC to connect to a SSL server in a blocking way and dispose the SocketWrapper object to release the memory and TCP connection.
Windows::Networking::HostName ^ hostname = ref new Windows::Networking::HostName(remoteAddr);
Windows::Foundation::IAsyncAction ^ op = _tcpSocket->ConnectAsync(hostname, remotePort.ToString(), SocketProtectionLevel::Ssl);
concurrency::task<void> connectTask(op);
connectTask.wait();More source code are posted at the end.
Observations:
- The sample will crash after certain amount of iterations and throws exception:
First-chance exception at 0x0000000000000000 in SocketStress.exe: 0xC0000005: Access violation executing location 0x0000000000000000.
Unhandled exception at 0x0000000000000000 in SocketStress.exe: 0xC0000005: Access violation executing location 0x0000000000000000.
2. The crash stack trace is as follows:
0000000000000000() Unknown
ntdll.dll!TppWorkerThread() Unknown
kernel32.dll!BaseThreadInitThunk‑() Unknown
ntdll.dll!RtlUserThreadStart‑() Unknown3. The crash happens sooner when more concurrent clients are running. In my sample, when 2 clients are started to concurrently connect to the server, and it takes just a few iteration for the sample to crash. When the number of client is 1, it may take up to a few hundred iterations to produce the crash.
4. I did not see the crash when without SSL.
======= CSharp code : MainPage.xmal.cs ============
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using System.Threading;
using WRC;namespace SocketStress
{
public sealed partial class MainPage : Page
{
const int Clients = 2;
const string DomainAddress = "rdvs.alljoyn.org";
const string RawAddress = "192.190.109.114";
bool ssl = true;
Task[] _clientTasks = new Task[Clients];
int _successCount = 0;
int _failCount = 0;
volatile int clientsRunning = 0;public MainPage()
{
this.InitializeComponent();
}protected override void OnNavigatedTo(NavigationEventArgs e)
{
}private void Button_Click_1(object sender, RoutedEventArgs e)
{
}private void Button_Click_2(object sender, RoutedEventArgs e)
{
if (clientsRunning != 0)
{
return;
}// Client start
for (int c = 0; c < Clients; c++)
{_clientTasks[c] = new Task(async () =>
{
while (true)
{SocketWrapper clientSocket = new SocketWrapper();
string addr;
int port = 0;
if (!ssl)
{
addr = RawAddress;
port = 80;
}
else
{
addr = DomainAddress;
port = 443;
}
clientSocket.Connect(addr, port);
bool success = true;
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
if (success)
{
successCount.Text = (++_successCount).ToString();
}
else
{
failCount.Text = (++_failCount).ToString();
}
});
clientSocket.Dispose();
}
});
_clientTasks[c].Start();
}
}
}
}======= C++ code : SocketWrapper.h ============
#pragma once
namespace WRC
{
public ref class SocketWrapper sealed
{
public:
SocketWrapper();
void SocketWrapper::Connect(Platform::String ^ remoteAddr, int remotePort);
virtual ~SocketWrapper();
void SocketWrapper::Close();
private:
Windows::Networking::Sockets::StreamSocket ^ _tcpSocket;
};
}======= C++ code : SocketWrapper.cpp ============
#include "pch.h"
#include "SocketWrapper.h"
#include "ppltasks.h"using namespace WRC;
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Networking::Sockets;
using namespace Windows::Storage::Streams;SocketWrapper::SocketWrapper()
{
if (nullptr == _tcpSocket) {
_tcpSocket = ref new StreamSocket();
}
}void SocketWrapper::Connect(Platform::String ^ remoteAddr, int remotePort)
{
try {
Windows::Networking::HostName ^ hostname = ref new Windows::Networking::HostName(remoteAddr);
Windows::Foundation::IAsyncAction ^ op = _tcpSocket->ConnectAsync(hostname, remotePort.ToString(), SocketProtectionLevel::Ssl);
try {
concurrency::task<void> connectTask(op);
connectTask.wait();
} catch (Platform::COMException ^ ex) {
auto m = ex->Message;
} catch (...) {
}
}catch (...) {
}
}void SocketWrapper::Close()
{
if(_tcpSocket != nullptr) {
delete _tcpSocket;
_tcpSocket = nullptr;
}
}SocketWrapper::~SocketWrapper() {
Close();
}Thursday, October 4, 2012 6:06 PM
Answers
-
The problem seems gone after installing the cumulative udate released on 10/09/2012
- Marked as answer by Jesse Jiang Thursday, October 11, 2012 2:25 AM
Wednesday, October 10, 2012 9:00 PM
All replies
-
Hi,
How about solutions in these thread?
Best regards,
Jesse
Jesse Jiang [MSFT]
MSDN Community Support | Feedback to us
Friday, October 5, 2012 7:34 AM -
Hi Jesse,
They are not the same problem. The symptoms are also very different. In my case, a worker thread in the threadpool suddently crashes without giving any clues.
My app does not crash if it uses the C# SocketStream API, in which case c++ PPL task api are not used.
Is there any way for me to upload my sample program for you to verify the problem? This is a big blocking issue to our project, and we really need to get it resolved.
Friday, October 5, 2012 6:12 PM -
Any followup on this? Thanks.Monday, October 8, 2012 10:49 PM
-
The problem seems gone after installing the cumulative udate released on 10/09/2012
- Marked as answer by Jesse Jiang Thursday, October 11, 2012 2:25 AM
Wednesday, October 10, 2012 9:00 PM