Skip to content

Commit 31ea0e6

Browse files
committed
CDRIVER-798 async_cmd checks for closed socket
Detects when server closes the connection on a call to ismaster.
1 parent 3c3019b commit 31ea0e6

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

src/mongoc/mongoc-async-cmd.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,13 @@ _mongoc_async_cmd_phase_recv_len (mongoc_async_cmd_t *acmd)
316316
return MONGOC_ASYNC_CMD_ERROR;
317317
}
318318

319+
if (bytes == 0) {
320+
bson_set_error (&acmd->error, MONGOC_ERROR_STREAM,
321+
MONGOC_ERROR_STREAM_SOCKET,
322+
"Server closed connection.");
323+
return MONGOC_ASYNC_CMD_ERROR;
324+
}
325+
319326
acmd->bytes_to_read -= bytes;
320327

321328
if (!acmd->bytes_to_read) {
@@ -353,6 +360,13 @@ _mongoc_async_cmd_phase_recv_rpc (mongoc_async_cmd_t *acmd)
353360
return MONGOC_ASYNC_CMD_ERROR;
354361
}
355362

363+
if (bytes == 0) {
364+
bson_set_error (&acmd->error, MONGOC_ERROR_STREAM,
365+
MONGOC_ERROR_STREAM_SOCKET,
366+
"Server closed connection.");
367+
return MONGOC_ASYNC_CMD_ERROR;
368+
}
369+
356370
acmd->bytes_to_read -= bytes;
357371

358372
if (!acmd->bytes_to_read) {

tests/test-mongoc-client.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,8 @@ test_seed_list (bool rs,
572572
mongoc_topology_description_t *td;
573573
mongoc_read_prefs_t *primary_pref;
574574
uint32_t discovered_nodes_len;
575+
int64_t start;
576+
int64_t duration_usec;
575577
bson_t reply;
576578
bson_error_t error;
577579
uint32_t id;
@@ -594,11 +596,11 @@ test_seed_list (bool rs,
594596
uri = mongoc_uri_new (uri_str);
595597
assert (uri);
596598

597-
/* TODO: CDRIVER-798 this shouldn't be needed in order to fail promptly
598-
* in single-threaded case. */
599-
/* must be >= minHeartbeatFrequencyMS=500 or the "reconnect"
600-
* case won't have time to succeed */
601-
mongoc_uri_set_option_as_int32 (uri, "serverSelectionTimeoutMS", 1000);
599+
if (pooled) {
600+
/* must be >= minHeartbeatFrequencyMS=500 or the "reconnect"
601+
* case won't have time to succeed */
602+
mongoc_uri_set_option_as_int32 (uri, "serverSelectionTimeoutMS", 1000);
603+
}
602604

603605
if (rs) {
604606
mock_server_auto_ismaster (server,
@@ -637,12 +639,18 @@ test_seed_list (bool rs,
637639
primary_pref = mongoc_read_prefs_new (MONGOC_READ_PRIMARY);
638640

639641
if (connection_option == CONNECT || connection_option == RECONNECT) {
642+
start = bson_get_monotonic_time ();
643+
640644
/* only localhost:port responds to initial discovery. the other seeds are
641645
* discarded from replica set topology, but remain for sharded. */
642646
ASSERT_OR_PRINT (mongoc_client_command_simple (
643647
client, "test", tmp_bson("{'foo': 1}"),
644648
primary_pref, &reply, &error), error);
645649

650+
/* discovery should be quick despite down servers, say < 100ms */
651+
duration_usec = bson_get_monotonic_time () - start;
652+
ASSERT_CMPINT ((int) (duration_usec / 1000), <, 100);
653+
646654
bson_destroy (&reply);
647655

648656
ASSERT_CMPINT (discovered_nodes_len, ==, (int) td->servers->items_len);
@@ -675,6 +683,12 @@ test_seed_list (bool rs,
675683
client, "test", tmp_bson("{'foo': 1}"),
676684
primary_pref, &reply, &error), error);
677685

686+
/* client waited for min heartbeat to pass before reconnecting, then
687+
* reconnected quickly despite down servers, say < 100ms later */
688+
duration_usec = bson_get_monotonic_time () - start;
689+
ASSERT_CMPINT ((int) (duration_usec / 1000), <,
690+
MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS + 100);
691+
678692
bson_destroy (&reply);
679693

680694
ASSERT_CMPINT (discovered_nodes_len, ==, (int) td->servers->items_len);

0 commit comments

Comments
 (0)