Skip to content

Commit 2dd0539

Browse files
Do not call stop on connection that failed to start (#70)
1 parent ea8d522 commit 2dd0539

File tree

3 files changed

+72
-16
lines changed

3 files changed

+72
-16
lines changed

src/signalrclient/hub_connection_impl.cpp

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -134,21 +134,9 @@ namespace signalr
134134

135135
if (start_exception)
136136
{
137-
connection->m_connection->stop([callback, weak_connection](std::exception_ptr ex)
138-
{
139-
try
140-
{
141-
auto connection = weak_connection.lock();
142-
if (!connection)
143-
{
144-
callback(std::make_exception_ptr(signalr_exception("the hub connection has been deconstructed")));
145-
return;
146-
}
147-
}
148-
catch (...) {}
149-
150-
callback(ex);
151-
}, start_exception);
137+
assert(connection->get_connection_state() == connection_state::disconnected);
138+
// connection didn't start, don't call stop
139+
callback(start_exception);
152140
return;
153141
}
154142

test/signalrclienttests/connection_impl_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1600,7 +1600,7 @@ TEST(connection_impl_stop, stop_cancels_ongoing_start_request)
16001600
ASSERT_TRUE(has_log_entry("[verbose ] connecting -> disconnected\n", log_entries)) << dump_vector(log_entries);
16011601
}
16021602

1603-
TEST(connection_impl_stop, ongoing_start_request_canceled_if_connection_stopped_before_init_message_received)
1603+
TEST(connection_impl_stop, ongoing_start_request_canceled_if_connection_stopped_before_negotiate_message_received)
16041604
{
16051605
auto stop_mre = manual_reset_event<void>();
16061606
auto done_mre = manual_reset_event<void>();

test/signalrclienttests/hub_connection_tests.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,74 @@ TEST(stop, pending_callbacks_finished_if_hub_connections_goes_out_of_scope)
818818
}
819819
}
820820

821+
TEST(stop, stops_with_inprogress_negotiate)
822+
{
823+
auto stop_mre = manual_reset_event<void>();
824+
auto done_mre = manual_reset_event<void>();
825+
auto websocket_client = create_test_websocket_client();
826+
auto http_client = std::shared_ptr<test_http_client>(new test_http_client([&stop_mre, &done_mre](const std::string& url, http_request, cancellation_token)
827+
{
828+
stop_mre.get();
829+
830+
auto response_body =
831+
url.find("/negotiate") != std::string::npos
832+
? "{ \"connectionId\" : \"f7707523-307d-4cba-9abf-3eef701241e8\", "
833+
"\"availableTransports\" : [ { \"transport\": \"WebSockets\", \"transferFormats\": [ \"Text\", \"Binary\" ] } ] }"
834+
: "";
835+
836+
done_mre.set();
837+
838+
return http_response{ 200, response_body };
839+
}));
840+
841+
auto hub_connection = hub_connection_builder::create(create_uri())
842+
.with_logging(std::make_shared<memory_log_writer>(), trace_level::verbose)
843+
.with_http_client_factory([http_client](const signalr_client_config& config)
844+
{
845+
http_client->set_scheduler(config.get_scheduler());
846+
return http_client;
847+
})
848+
.with_websocket_factory([websocket_client](const signalr_client_config& config)
849+
{
850+
websocket_client->set_config(config);
851+
return websocket_client;
852+
})
853+
.build();
854+
855+
auto disconnected_called = false;
856+
// disconnected not called for connections that never started successfully
857+
hub_connection.set_disconnected([&disconnected_called](std::exception_ptr ex)
858+
{
859+
disconnected_called = true;
860+
});
861+
862+
auto mre = manual_reset_event<void>();
863+
hub_connection.start([&mre](std::exception_ptr exception)
864+
{
865+
mre.set(exception);
866+
});
867+
868+
hub_connection.stop([&stop_mre](std::exception_ptr exception)
869+
{
870+
stop_mre.set(exception);
871+
});
872+
873+
try
874+
{
875+
mre.get();
876+
ASSERT_TRUE(false);
877+
}
878+
catch (const signalr::canceled_exception&)
879+
{
880+
}
881+
882+
// avoid AV from accessing stop_mre in callback
883+
done_mre.get();
884+
885+
ASSERT_EQ(connection_state::disconnected, hub_connection.get_connection_state());
886+
ASSERT_FALSE(disconnected_called);
887+
}
888+
821889
TEST(hub_invocation, hub_connection_invokes_users_code_on_hub_invocations)
822890
{
823891
auto websocket_client = create_test_websocket_client();

0 commit comments

Comments
 (0)