Skip to content

Commit e66b022

Browse files
committed
CDRIVER-2237 distinguish network timeout and error
1 parent 12e643a commit e66b022

15 files changed

+226
-65
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mongo-c-driver 1.8.0
88
* mongoc_collection_create_index and mongoc_collection_create_index_with_opts
99
are both now deprecated. Use mongoc_database_write_command_with_opts
1010
instead; a guide to creating an index using that function has been added.
11+
* New stream method mongoc_stream_timed_out.
1112

1213
Thanks to everyone who contributed to the development of this release.
1314

doc/mongoc_stream_t.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ There are a number of built in stream types that come with mongoc. The default c
3737
mongoc_stream_read
3838
mongoc_stream_readv
3939
mongoc_stream_setsockopt
40+
mongoc_stream_timed_out
4041
mongoc_stream_uncork
4142
mongoc_stream_write
4243
mongoc_stream_writev

doc/mongoc_stream_timed_out.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
:man_page: mongoc_stream_timed_out
2+
3+
mongoc_stream_timed_out()
4+
=========================
5+
6+
Synopsis
7+
--------
8+
9+
.. code-block:: c
10+
11+
bool
12+
mongoc_stream_timed_out (mongoc_stream_t *stream);
13+
14+
Parameters
15+
----------
16+
17+
* ``stream``: A :symbol:`mongoc_stream_t`.
18+
19+
Returns
20+
-------
21+
22+
True if there has been a network timeout error on this stream.

src/mongoc/mongoc-errno-private.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,18 @@ BSON_BEGIN_DECLS
3535
#if defined(_WIN32)
3636
#define MONGOC_ERRNO_IS_AGAIN(errno) \
3737
((errno == EAGAIN) || (errno == WSAEWOULDBLOCK) || (errno == WSAEINPROGRESS))
38+
#define MONGOC_ERRNO_IS_TIMEDOUT(errno) (errno == WSAETIMEDOUT)
3839
#elif defined(__sun)
3940
/* for some reason, accept() returns -1 and errno of 0 */
4041
#define MONGOC_ERRNO_IS_AGAIN(errno) \
4142
((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK) || \
4243
(errno == EINPROGRESS) || (errno == 0))
44+
#define MONGOC_ERRNO_IS_TIMEDOUT(errno) (errno == ETIMEDOUT)
4345
#else
4446
#define MONGOC_ERRNO_IS_AGAIN(errno) \
4547
((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK) || \
4648
(errno == EINPROGRESS))
49+
#define MONGOC_ERRNO_IS_TIMEDOUT(errno) (errno == ETIMEDOUT)
4750
#endif
4851

4952

src/mongoc/mongoc-socket.c

Lines changed: 54 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,35 @@
3939
/* either struct sockaddr or void, depending on platform */
4040
typedef MONGOC_SOCKET_ARG2 mongoc_sockaddr_t;
4141

42+
43+
/*
44+
*--------------------------------------------------------------------------
45+
*
46+
* _mongoc_socket_capture_errno --
47+
*
48+
* Save the errno state for contextual use.
49+
*
50+
* Returns:
51+
* None.
52+
*
53+
* Side effects:
54+
* None.
55+
*
56+
*--------------------------------------------------------------------------
57+
*/
58+
59+
static void
60+
_mongoc_socket_capture_errno (mongoc_socket_t *sock) /* IN */
61+
{
62+
#ifdef _WIN32
63+
errno = sock->errno_ = WSAGetLastError ();
64+
#else
65+
sock->errno_ = errno;
66+
#endif
67+
TRACE ("setting errno: %d %s", sock->errno_, strerror (sock->errno_));
68+
}
69+
70+
4271
/*
4372
*--------------------------------------------------------------------------
4473
*
@@ -99,13 +128,9 @@ _mongoc_socket_setnonblock (int sd)
99128
*/
100129

101130
static bool
102-
#ifdef _WIN32
103-
_mongoc_socket_wait (SOCKET sd, /* IN */
104-
#else
105-
_mongoc_socket_wait (int sd, /* IN */
106-
#endif
107-
int events, /* IN */
108-
int64_t expire_at) /* IN */
131+
_mongoc_socket_wait (mongoc_socket_t *sock, /* IN */
132+
int events, /* IN */
133+
int64_t expire_at) /* IN */
109134
{
110135
#ifdef _WIN32
111136
fd_set read_fds;
@@ -121,6 +146,7 @@ _mongoc_socket_wait (int sd, /* IN */
121146

122147
ENTRY;
123148

149+
BSON_ASSERT (sock);
124150
BSON_ASSERT (events);
125151

126152
#ifdef _WIN32
@@ -129,16 +155,16 @@ _mongoc_socket_wait (int sd, /* IN */
129155
FD_ZERO (&error_fds);
130156

131157
if (events & POLLIN) {
132-
FD_SET (sd, &read_fds);
158+
FD_SET (sock->sd, &read_fds);
133159
}
134160

135161
if (events & POLLOUT) {
136-
FD_SET (sd, &write_fds);
162+
FD_SET (sock->sd, &write_fds);
137163
}
138164

139-
FD_SET (sd, &error_fds);
165+
FD_SET (sock->sd, &error_fds);
140166
#else
141-
pfd.fd = sd;
167+
pfd.fd = sock->sd;
142168
pfd.events = events | POLLERR | POLLHUP;
143169
pfd.revents = 0;
144170
#endif
@@ -167,9 +193,9 @@ _mongoc_socket_wait (int sd, /* IN */
167193
0 /*unused*/, &read_fds, &write_fds, &error_fds, &timeout_tv);
168194
}
169195
if (ret == SOCKET_ERROR) {
170-
errno = WSAGetLastError ();
196+
_mongoc_socket_capture_errno (sock);
171197
ret = -1;
172-
} else if (FD_ISSET (sd, &error_fds)) {
198+
} else if (FD_ISSET (sock->sd, &error_fds)) {
173199
errno = WSAECONNRESET;
174200
ret = -1;
175201
}
@@ -180,7 +206,8 @@ _mongoc_socket_wait (int sd, /* IN */
180206
if (ret > 0) {
181207
/* Something happened, so return that */
182208
#ifdef _WIN32
183-
return (FD_ISSET (sd, &read_fds) || FD_ISSET (sd, &write_fds));
209+
return (FD_ISSET (sock->sd, &read_fds)
210+
|| FD_ISSET (sock->sd, &write_fds));
184211
#else
185212
RETURN (0 != (pfd.revents & events));
186213
#endif
@@ -192,16 +219,23 @@ _mongoc_socket_wait (int sd, /* IN */
192219
now = bson_get_monotonic_time ();
193220

194221
if (expire_at < now) {
222+
_mongoc_socket_capture_errno (sock);
195223
RETURN (false);
196224
} else {
197225
continue;
198226
}
199227
} else {
200228
/* poll failed for some non-transient reason */
229+
_mongoc_socket_capture_errno (sock);
201230
RETURN (false);
202231
}
203232
} else {
204-
/* ret == 0, poll timed out */
233+
/* ret == 0, poll timed out */
234+
#ifdef _WIN32
235+
sock->errno_ = timeout ? WSAETIMEDOUT : EAGAIN;
236+
#else
237+
sock->errno_ = timeout ? ETIMEDOUT : EAGAIN;
238+
#endif
205239
RETURN (false);
206240
}
207241
}
@@ -560,34 +594,6 @@ mongoc_socket_errno (mongoc_socket_t *sock) /* IN */
560594
}
561595

562596

563-
/*
564-
*--------------------------------------------------------------------------
565-
*
566-
* _mongoc_socket_capture_errno --
567-
*
568-
* Save the errno state for contextual use.
569-
*
570-
* Returns:
571-
* None.
572-
*
573-
* Side effects:
574-
* None.
575-
*
576-
*--------------------------------------------------------------------------
577-
*/
578-
579-
static void
580-
_mongoc_socket_capture_errno (mongoc_socket_t *sock) /* IN */
581-
{
582-
#ifdef _WIN32
583-
errno = sock->errno_ = WSAGetLastError ();
584-
#else
585-
sock->errno_ = errno;
586-
#endif
587-
TRACE ("setting errno: %d %s", sock->errno_, strerror (sock->errno_));
588-
}
589-
590-
591597
/*
592598
*--------------------------------------------------------------------------
593599
*
@@ -689,7 +695,7 @@ mongoc_socket_accept_ex (mongoc_socket_t *sock, /* IN */
689695
try_again = (failed && _mongoc_socket_errno_is_again (sock));
690696

691697
if (failed && try_again) {
692-
if (_mongoc_socket_wait (sock->sd, POLLIN, expire_at)) {
698+
if (_mongoc_socket_wait (sock, POLLIN, expire_at)) {
693699
GOTO (again);
694700
}
695701
RETURN (NULL);
@@ -849,7 +855,7 @@ mongoc_socket_connect (mongoc_socket_t *sock, /* IN */
849855
}
850856

851857
if (failed && try_again) {
852-
if (_mongoc_socket_wait (sock->sd, POLLOUT, expire_at)) {
858+
if (_mongoc_socket_wait (sock, POLLOUT, expire_at)) {
853859
optval = -1;
854860
ret = getsockopt (
855861
sock->sd, SOL_SOCKET, SO_ERROR, (char *) &optval, &optlen);
@@ -1058,7 +1064,7 @@ mongoc_socket_recv (mongoc_socket_t *sock, /* IN */
10581064
if (failed) {
10591065
_mongoc_socket_capture_errno (sock);
10601066
if (_mongoc_socket_errno_is_again (sock) &&
1061-
_mongoc_socket_wait (sock->sd, POLLIN, expire_at)) {
1067+
_mongoc_socket_wait (sock, POLLIN, expire_at)) {
10621068
GOTO (again);
10631069
}
10641070
}
@@ -1408,7 +1414,7 @@ mongoc_socket_sendv (mongoc_socket_t *sock, /* IN */
14081414
/*
14091415
* Block on poll() until our desired condition is met.
14101416
*/
1411-
if (!_mongoc_socket_wait (sock->sd, POLLOUT, expire_at)) {
1417+
if (!_mongoc_socket_wait (sock, POLLOUT, expire_at)) {
14121418
GOTO (CLEANUP);
14131419
}
14141420
}
@@ -1469,7 +1475,7 @@ mongoc_socket_check_closed (mongoc_socket_t *sock) /* IN */
14691475
char buf[1];
14701476
ssize_t r;
14711477

1472-
if (_mongoc_socket_wait (sock->sd, POLLIN, 0)) {
1478+
if (_mongoc_socket_wait (sock, POLLIN, 0)) {
14731479
sock->errno_ = 0;
14741480

14751481
r = recv (sock->sd, buf, 1, MSG_PEEK);

src/mongoc/mongoc-stream-buffered.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,15 @@ _mongoc_stream_buffered_check_closed (mongoc_stream_t *stream) /* IN */
275275
}
276276

277277

278+
static bool
279+
_mongoc_stream_buffered_timed_out (mongoc_stream_t *stream) /* IN */
280+
{
281+
mongoc_stream_buffered_t *buffered = (mongoc_stream_buffered_t *) stream;
282+
BSON_ASSERT (stream);
283+
return mongoc_stream_timed_out (buffered->base_stream);
284+
}
285+
286+
278287
/*
279288
*--------------------------------------------------------------------------
280289
*
@@ -316,6 +325,7 @@ mongoc_stream_buffered_new (mongoc_stream_t *base_stream, /* IN */
316325
stream->stream.readv = mongoc_stream_buffered_readv;
317326
stream->stream.get_base_stream = _mongoc_stream_buffered_get_base_stream;
318327
stream->stream.check_closed = _mongoc_stream_buffered_check_closed;
328+
stream->stream.timed_out = _mongoc_stream_buffered_timed_out;
319329

320330
stream->base_stream = base_stream;
321331

src/mongoc/mongoc-stream-socket.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
#include "mongoc-stream-private.h"
1919
#include "mongoc-stream-socket.h"
2020
#include "mongoc-trace-private.h"
21-
21+
#include "mongoc-socket-private.h"
22+
#include "mongoc-errno-private.h"
2223

2324
#undef MONGOC_LOG_DOMAIN
2425
#define MONGOC_LOG_DOMAIN "stream"
@@ -275,6 +276,20 @@ _mongoc_stream_socket_check_closed (mongoc_stream_t *stream) /* IN */
275276
}
276277

277278

279+
static bool
280+
_mongoc_stream_socket_timed_out (mongoc_stream_t *stream) /* IN */
281+
{
282+
mongoc_stream_socket_t *ss = (mongoc_stream_socket_t *) stream;
283+
284+
ENTRY;
285+
286+
BSON_ASSERT (ss);
287+
BSON_ASSERT (ss->sock);
288+
289+
RETURN (MONGOC_ERRNO_IS_TIMEDOUT (ss->sock->errno_));
290+
}
291+
292+
278293
/*
279294
*--------------------------------------------------------------------------
280295
*
@@ -309,6 +324,7 @@ mongoc_stream_socket_new (mongoc_socket_t *sock) /* IN */
309324
stream->vtable.writev = _mongoc_stream_socket_writev;
310325
stream->vtable.setsockopt = _mongoc_stream_socket_setsockopt;
311326
stream->vtable.check_closed = _mongoc_stream_socket_check_closed;
327+
stream->vtable.timed_out = _mongoc_stream_socket_timed_out;
312328
stream->vtable.poll = _mongoc_stream_socket_poll;
313329
stream->sock = sock;
314330

src/mongoc/mongoc-stream-tls-libressl.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,16 @@ mongoc_stream_tls_libressl_handshake (mongoc_stream_t *stream,
441441
RETURN (false);
442442
}
443443

444+
static bool
445+
_mongoc_stream_tls_libressl_timed_out (mongoc_stream_t *stream)
446+
{
447+
mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *) stream;
448+
449+
ENTRY;
450+
451+
RETURN (mongoc_stream_timed_out (tls->base_stream));
452+
}
453+
444454
mongoc_stream_t *
445455
mongoc_stream_tls_libressl_new (mongoc_stream_t *base_stream,
446456
const char *host,
@@ -474,6 +484,7 @@ mongoc_stream_tls_libressl_new (mongoc_stream_t *base_stream,
474484
tls->parent.setsockopt = _mongoc_stream_tls_libressl_setsockopt;
475485
tls->parent.get_base_stream = _mongoc_stream_tls_libressl_get_base_stream;
476486
tls->parent.check_closed = _mongoc_stream_tls_libressl_check_closed;
487+
tls->parent.timed_out = _mongoc_stream_tls_libressl_timed_out;
477488
memcpy (&tls->ssl_opts, opt, sizeof tls->ssl_opts);
478489
tls->handshake = mongoc_stream_tls_libressl_handshake;
479490
tls->ctx = (void *) libressl;

src/mongoc/mongoc-stream-tls-openssl.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,16 @@ _mongoc_stream_tls_openssl_sni (SSL *ssl, int *ad, void *arg)
616616
return SSL_TLSEXT_ERR_OK;
617617
}
618618

619+
static bool
620+
_mongoc_stream_tls_openssl_timed_out (mongoc_stream_t *stream)
621+
{
622+
mongoc_stream_tls_t *tls = (mongoc_stream_tls_t *) stream;
623+
624+
ENTRY;
625+
626+
RETURN (mongoc_stream_timed_out (tls->base_stream));
627+
}
628+
619629
/*
620630
*--------------------------------------------------------------------------
621631
*
@@ -735,6 +745,7 @@ mongoc_stream_tls_openssl_new (mongoc_stream_t *base_stream,
735745
tls->parent.setsockopt = _mongoc_stream_tls_openssl_setsockopt;
736746
tls->parent.get_base_stream = _mongoc_stream_tls_openssl_get_base_stream;
737747
tls->parent.check_closed = _mongoc_stream_tls_openssl_check_closed;
748+
tls->parent.timed_out = _mongoc_stream_tls_openssl_timed_out;
738749
memcpy (&tls->ssl_opts, opt, sizeof tls->ssl_opts);
739750
tls->handshake = mongoc_stream_tls_openssl_handshake;
740751
tls->ctx = (void *) openssl;

0 commit comments

Comments
 (0)