CPPRestSDK (casablanca) Безопасность темы
Безопасно ли создавать websocket_callback_client
и настройте функцию обратного вызова в главном потоке, затем вызовите websocket_callback_client::send()
из отдельной ветки?
Я получаю необработанное исключение _REPORT_PPLTASK_UNOBSERVED_EXCEPTION()
и я верю, что именно поэтому.
У меня есть класс таймера, который вызывает функцию с заданным интервалом, вызов этой функции обрабатывается работником std::thread
, Функция содержит вызов websocket_callback_client::send()
и необработанное исключение указывает на этот вызов. Иногда функция вылетает из приложения при первом вызове, иногда при втором вызове. Это приводит меня к мысли, что это состояние гонки.
Функция вызова рабочих потоков - это просто:
void OnTick()
{
printf("Heartbeat ");
rapidjson::StringBuffer OutJSON;
rapidjson::Writer<rapidjson::StringBuffer> writer(OutJSON);
writer.StartObject();
writer.Key("op");
writer.Int(1);
writer.Key("d");
writer.Null();
writer.EndObject();
websocket_outgoing_message msg;
msg.set_utf8_message(OutJSON.GetString());
wsClient.send(msg).then([=]() { printf("Sent\n"); });
}
_M_stackTrace:
{[capacity]=10 [allocator]=allocator [0]=0x00007ff82ebb89d3 {cpprest_2_10.dll!web::websockets::client::websocket_outgoing_message::signal_body_sent(const std::exception_ptr & e), Line 150} ...} Concurrency::details::_TaskCreationCallstack [0] 0x00007ff82ebb89d3 {cpprest_2_10.dll!web::websockets::client::websocket_outgoing_message::signal_body_sent(const std::exception_ptr & e), Line 150} void * [1] 0x00007ff82eaf869a {cpprest_2_10.dll!web::websockets::client::details::wspp_callback_client::send_msg::__l2::<lambda>(Concurrency::task<std::error_code> previousTask), Line 561} void * [2] 0x00007ff82ea1ac40 {cpprest_2_10.dll!std::_Invoker_functor::_Call<void <lambda>(Concurrency::task<std::error_code>) & __ptr64,Concurrency::task<std::error_code> >(web::websockets::client::details::wspp_callback_client::send_msg::__l2::void <lambda>(Concurrency::task<std::error_code>) & _Obj, Concurrency::task<std::error_code> && <_Args_0>), Line 1790} void * [3] 0x00007ff82ea865ac {cpprest_2_10.dll!std::invoke<void <lambda>(Concurrency::task<std::error_code>) & __ptr64,Concurrency::task<std::error_code> >(web::websockets::client::details::wspp_callback_client::send_msg::__l2::void <lambda>(Concurrency::task<std::error_code>) & _Obj, Concurrency::task<std::error_code> && <_Args_0>), Line 1790} void * [4] 0x00007ff82ea1abbc {cpprest_2_10.dll!std::_Invoker_ret<void,1>::_Call<void <lambda>(Concurrency::task<std::error_code>) & __ptr64,Concurrency::task<std::error_code> >(web::websockets::client::details::wspp_callback_client::send_msg::__l2::void <lambda>(Concurrency::task<std::error_code>) & <_Vals_0>, Concurrency::task<std::error_code> && <_Vals_1>), Line 1816} void * [5] 0x00007ff82eb2542e {cpprest_2_10.dll!std::_Func_impl_no_alloc<void <lambda>(Concurrency::task<std::error_code>),void,Concurrency::task<std::error_code> >::_Do_call(Concurrency::task<std::error_code> && <_Args_0>), Line 300} void * [6] 0x00007ff82eafd1f8 {cpprest_2_10.dll!std::_Func_class<void,Concurrency::task<std::error_code> >::operator()(Concurrency::task<std::error_code> <_Args_0>), Line 350} void * [7] 0x00007ff82eafc12c {cpprest_2_10.dll!Concurrency::details::_MakeTToUnitFunc::__l2::<lambda>(Concurrency::task<std::error_code> _Obj), Line 2313} void * [8] 0x00007ff82ea1db70 {cpprest_2_10.dll!std::_Invoker_functor::_Call<unsigned char <lambda>(Concurrency::task<std::error_code>) & __ptr64,Concurrency::task<std::error_code> >(Concurrency::details::_MakeTToUnitFunc::__l2::unsigned char <lambda>(Concurrency::task<std::error_code>) & _Obj, Concurrency::task<std::error_code> && <_Args_0>), Line 1790} void * [9] 0x00007ff82ea87cac {cpprest_2_10.dll!std::invoke<unsigned char <lambda>(Concurrency::task<std::error_code>) & __ptr64,Concurrency::task<std::error_code> >(Concurrency::details::_MakeTToUnitFunc::__l2::unsigned char <lambda>(Concurrency::task<std::error_code>) & _Obj, Concurrency::task<std::error_code> && <_Args_0>), Line 1790} void *
Я пытался заменить OutJSON.GetString()
в моей вызывающей функции с вручную созданной строкой JSON, чтобы убедиться, что мы передаем правильную строку JSON. Либо этот аспект библиотеки является потокобезопасным, а что-то еще не так, или мне нужно выяснить, как реализовать мьютекс вокруг wsClient
или придумать другой механизм синхронизации / интервала.