summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsniukalov <sniukaov@luxoft.com>2019-12-11 10:23:11 +0200
committersniukalov <sniukaov@luxoft.com>2019-12-24 14:40:24 +0200
commite5670fc5e82538ce98aac26cd2149d9b7a03d839 (patch)
tree15676a3a61b89cff764be27e82ce69fa6585028b
parente137556512215ded94228e33d21ab4c3e1af3017 (diff)
downloadsdl_core-fix/crash_in_websocket_session_on_start.tar.gz
Fix crash in WebsocketSession on start.fix/crash_in_websocket_session_on_start
A crash occurs because we use an overload of boost::beast::websocket::stream::write without error_code. After the error occurs we add an error message to the logger and continue working. In SendMessage_UnpreparedConnection_WithoutFall test we use sleep because we can't ability to catch processed event. This issue is that LoopThreadDelegate requires a WebsocketSession to work. WebsocketSession init LoopThreadDelegate with 'this', so we have no way to simulate it without additional installers. In future, to avoid sleep, we can: Create a wrapper class for the socket, then provide the socket layout for the WebsocketSession in unit tests and wrap the following interfaces: async_read write down get_executor async_accept
-rw-r--r--src/components/hmi_message_handler/src/websocket_session.cc14
-rw-r--r--src/components/hmi_message_handler/test/hmi_message_handler_impl_test.cc40
2 files changed, 48 insertions, 6 deletions
diff --git a/src/components/hmi_message_handler/src/websocket_session.cc b/src/components/hmi_message_handler/src/websocket_session.cc
index 3d18da19d2..ad9d5273e4 100644
--- a/src/components/hmi_message_handler/src/websocket_session.cc
+++ b/src/components/hmi_message_handler/src/websocket_session.cc
@@ -304,12 +304,14 @@ void WebsocketSession::LoopThreadDelegate::exitThreadMain() {
}
void WebsocketSession::LoopThreadDelegate::DrainQueue() {
- while (!message_queue_.empty()) {
- Message message_ptr;
- message_queue_.pop(message_ptr);
- if (!shutdown_) {
- handler_.ws_.write(boost::asio::buffer(*message_ptr));
- };
+ Message message_ptr;
+ while (!shutdown_ && message_queue_.pop(message_ptr)) {
+ boost::system::error_code ec;
+ handler_.ws_.write(boost::asio::buffer(*message_ptr), ec);
+ if (ec) {
+ LOG4CXX_ERROR(ws_logger_,
+ "A system error has occurred: " << ec.message());
+ }
}
}
diff --git a/src/components/hmi_message_handler/test/hmi_message_handler_impl_test.cc b/src/components/hmi_message_handler/test/hmi_message_handler_impl_test.cc
index eaa274d0f4..f38eb019e2 100644
--- a/src/components/hmi_message_handler/test/hmi_message_handler_impl_test.cc
+++ b/src/components/hmi_message_handler/test/hmi_message_handler_impl_test.cc
@@ -189,6 +189,46 @@ TEST_F(HMIMessageHandlerImplTest, SendMessageToHMI_Success) {
EXPECT_TRUE(waiter.WaitFor(1, 100));
}
+TEST(WebsocketSessionTest, SendMessage_UnpreparedConnection_WithoutFall) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+
+ auto send_message = []() {
+ auto message =
+ "{\"id\" : 1,\"jsonrpc\" : \"2.0\",\"method\" : "
+ "\"BasicCommunication.GetSystemInfo\"}";
+
+ Json::Reader reader;
+ Json::Value json_value;
+
+ ASSERT_TRUE(reader.parse(message, json_value, false));
+
+ // Make unprepared connection
+ boost::asio::io_context ioc{1};
+ boost::asio::ip::tcp::acceptor acceptor{
+ ioc, {boost::asio::ip::make_address("127.0.0.1"), 8087}};
+ boost::asio::ip::tcp::socket socket{ioc};
+
+ std::unique_ptr<hmi_message_handler::WebsocketSession> session(
+ new hmi_message_handler::WebsocketSession(std::move(socket), nullptr));
+
+ // Send message to unprepared connection
+ session->sendJsonMessage(json_value);
+
+ // Wait for the message to be processed
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ // Stopping connection thread
+ session->Shutdown();
+ session = nullptr;
+
+ exit(0);
+ };
+
+ // Expected exit code 0, if test terminate by other signal(SIGABRT or
+ // SIGSEGV), we will get failed test
+ EXPECT_EXIT(send_message(), ::testing::ExitedWithCode(0), "");
+}
+
} // namespace hmi_message_handler_test
} // namespace components
} // namespace test