@@ -134,23 +134,22 @@ class winrt_callback_client : public websocket_client_callback_impl, public std:
134
134
{
135
135
m_external_close_handler (status, reason, error_code);
136
136
}
137
+
138
+ // Locally copy the task completion event since there is a PPL bug
139
+ // that the set method accesses internal state in the event and the websocket
140
+ // client could be destroyed.
141
+ auto local_close_tce = m_close_tce;
137
142
m_close_tce.set ();
138
- m_server_close_complete.set ();
139
143
});
140
144
}
141
145
142
146
~winrt_callback_client ()
143
147
{
144
- // task_completion_event::set() returns false if it has already been set.
145
- // In that case, wait on the m_server_close_complete event for the tce::set() to complete.
146
- // The websocket client on close handler (upon receiving close frame from server) will
147
- // set this event.
148
- // If we have not received a close frame from the server, this set will be a no-op as the
149
- // websocket_client is anyways destructing.
150
- if (!m_close_tce.set ())
151
- {
152
- m_server_close_complete.wait ();
153
- }
148
+ // Locally copy the task completion event since there is a PPL bug
149
+ // that the set method accesses internal state in the event and the websocket
150
+ // client could be destroyed.
151
+ auto local_close_tce = m_close_tce;
152
+ m_close_tce.set ();
154
153
}
155
154
156
155
pplx::task<void > connect ()
@@ -161,6 +160,8 @@ class winrt_callback_client : public websocket_client_callback_impl, public std:
161
160
return pplx::task_from_exception<void >(websocket_exception (" Only a default proxy server is supported." ));
162
161
}
163
162
163
+
164
+
164
165
const auto &proxy_cred = proxy.credentials ();
165
166
if (proxy_cred.is_set ())
166
167
{
@@ -409,12 +410,6 @@ class winrt_callback_client : public websocket_client_callback_impl, public std:
409
410
ReceiveContext ^ m_context;
410
411
411
412
pplx::task_completion_event<void > m_close_tce;
412
- // There is a bug in ppl task_completion_event. The task_completion_event::set() accesses some
413
- // internal data after signaling the event. The waiting thread might go ahead and start destroying the
414
- // websocket_client. Due to this race, set() can cause a crash.
415
- // To workaround this bug, maintain another event: m_server_close_complete. We will signal this when the m_close_tce.set() has
416
- // completed. The websocket_client destructor can wait on this event before proceeding.
417
- Concurrency::event m_server_close_complete;
418
413
419
414
// External callback for handling received and close event
420
415
std::function<void (websocket_incoming_message)> m_external_message_handler;
0 commit comments