summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerhii Niukalov (GitHub) <36993782+SNiukalov@users.noreply.github.com>2020-01-10 18:05:19 +0200
committerCollin <iCollin@users.noreply.github.com>2020-01-10 11:05:18 -0500
commitf113bc7dfb651908cdd8b68db1a634c798f88e89 (patch)
tree535fc76846dc66cb655762f77b84a06253815ff4
parent49c29364460faa527bc758d0fd6b108463f8d82d (diff)
downloadsdl_core-f113bc7dfb651908cdd8b68db1a634c798f88e89.tar.gz
Fix crash in WebsocketSession on start. (#3191)
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