@@ -108,7 +108,10 @@ _mongoc_socket_wait (int sd, /* IN */
108
108
int64_t expire_at ) /* IN */
109
109
{
110
110
#ifdef _WIN32
111
- WSAPOLLFD pfd ;
111
+ fd_set read_fds ;
112
+ fd_set write_fds ;
113
+ fd_set error_fds ;
114
+ struct timeval timeout_tv ;
112
115
#else
113
116
struct pollfd pfd ;
114
117
#endif
@@ -120,14 +123,25 @@ _mongoc_socket_wait (int sd, /* IN */
120
123
121
124
BSON_ASSERT (events );
122
125
123
- pfd .fd = sd ;
124
126
#ifdef _WIN32
125
- pfd .events = events ;
127
+ FD_ZERO (& read_fds );
128
+ FD_ZERO (& write_fds );
129
+ FD_ZERO (& error_fds );
130
+
131
+ if (events & POLLIN ) {
132
+ FD_SET (sd , & read_fds );
133
+ }
134
+
135
+ if (events & POLLOUT ) {
136
+ FD_SET (sd , & write_fds );
137
+ }
138
+
139
+ FD_SET (sd , & error_fds );
126
140
#else
141
+ pfd .fd = sd ;
127
142
pfd .events = events | POLLERR | POLLHUP ;
128
- #endif
129
143
pfd .revents = 0 ;
130
-
144
+ #endif
131
145
now = bson_get_monotonic_time ();
132
146
133
147
for (;;) {
@@ -143,10 +157,21 @@ _mongoc_socket_wait (int sd, /* IN */
143
157
}
144
158
145
159
#ifdef _WIN32
146
- ret = WSAPoll (& pfd , 1 , timeout );
160
+ if (timeout == -1 ) {
161
+ /* not WSAPoll: daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken */
162
+ ret = select (0 /*unused*/ , & read_fds , & write_fds , & error_fds , NULL );
163
+ } else {
164
+ timeout_tv .tv_sec = timeout / 1000 ;
165
+ timeout_tv .tv_usec = (timeout % 1000 ) * 1000 ;
166
+ ret = select (
167
+ 0 /*unused*/ , & read_fds , & write_fds , & error_fds , & timeout_tv );
168
+ }
147
169
if (ret == SOCKET_ERROR ) {
148
170
errno = WSAGetLastError ();
149
171
ret = -1 ;
172
+ } else if (FD_ISSET (sd , & error_fds )) {
173
+ errno = WSAECONNRESET ;
174
+ ret = -1 ;
150
175
}
151
176
#else
152
177
ret = poll (& pfd , 1 , timeout );
@@ -155,7 +180,7 @@ _mongoc_socket_wait (int sd, /* IN */
155
180
if (ret > 0 ) {
156
181
/* Something happened, so return that */
157
182
#ifdef _WIN32
158
- RETURN ( 0 != ( pfd . revents & ( events | POLLHUP | POLLERR ) ));
183
+ return ( FD_ISSET ( sd , & read_fds ) || FD_ISSET ( sd , & write_fds ));
159
184
#else
160
185
RETURN (0 != (pfd .revents & events ));
161
186
#endif
@@ -176,7 +201,7 @@ _mongoc_socket_wait (int sd, /* IN */
176
201
RETURN (false);
177
202
}
178
203
} else {
179
- /* poll timed out */
204
+ /* ret == 0, poll timed out */
180
205
RETURN (false);
181
206
}
182
207
}
@@ -210,7 +235,10 @@ mongoc_socket_poll (mongoc_socket_poll_t *sds, /* IN */
210
235
int32_t timeout ) /* IN */
211
236
{
212
237
#ifdef _WIN32
213
- WSAPOLLFD * pfds ;
238
+ fd_set read_fds ;
239
+ fd_set write_fds ;
240
+ fd_set error_fds ;
241
+ struct timeval timeout_tv ;
214
242
#else
215
243
struct pollfd * pfds ;
216
244
#endif
@@ -222,36 +250,59 @@ mongoc_socket_poll (mongoc_socket_poll_t *sds, /* IN */
222
250
BSON_ASSERT (sds );
223
251
224
252
#ifdef _WIN32
225
- pfds = (WSAPOLLFD * ) bson_malloc (sizeof (* pfds ) * nsds );
253
+ FD_ZERO (& read_fds );
254
+ FD_ZERO (& write_fds );
255
+ FD_ZERO (& error_fds );
256
+
257
+ for (i = 0 ; i < nsds ; i ++ ) {
258
+ if (sds [i ].events & POLLIN ) {
259
+ FD_SET (sds [i ].socket -> sd , & read_fds );
260
+ }
261
+
262
+ if (sds [i ].events & POLLOUT ) {
263
+ FD_SET (sds [i ].socket -> sd , & write_fds );
264
+ }
265
+
266
+ FD_SET (sds [i ].socket -> sd , & error_fds );
267
+ }
268
+
269
+ timeout_tv .tv_sec = timeout / 1000 ;
270
+ timeout_tv .tv_usec = (timeout % 1000 ) * 1000 ;
271
+
272
+ /* not WSAPoll: daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken */
273
+ ret = select (0 /*unused*/ , & read_fds , & write_fds , & error_fds , & timeout_tv );
274
+ if (ret == SOCKET_ERROR ) {
275
+ errno = WSAGetLastError ();
276
+ return -1 ;
277
+ }
278
+
279
+ for (i = 0 ; i < nsds ; i ++ ) {
280
+ if (FD_ISSET (sds [i ].socket -> sd , & read_fds )) {
281
+ sds [i ].revents = POLLIN ;
282
+ } else if (FD_ISSET (sds [i ].socket -> sd , & write_fds )) {
283
+ sds [i ].revents = POLLOUT ;
284
+ } else if (FD_ISSET (sds [i ].socket -> sd , & error_fds )) {
285
+ sds [i ].revents = POLLHUP ;
286
+ } else {
287
+ sds [i ].revents = 0 ;
288
+ }
289
+ }
226
290
#else
227
291
pfds = (struct pollfd * ) bson_malloc (sizeof (* pfds ) * nsds );
228
- #endif
229
292
230
293
for (i = 0 ; i < nsds ; i ++ ) {
231
294
pfds [i ].fd = sds [i ].socket -> sd ;
232
- #ifdef _WIN32
233
- pfds [i ].events = sds [i ].events ;
234
- #else
235
295
pfds [i ].events = sds [i ].events | POLLERR | POLLHUP ;
236
- #endif
237
296
pfds [i ].revents = 0 ;
238
297
}
239
298
240
- #ifdef _WIN32
241
- ret = WSAPoll (pfds , nsds , timeout );
242
- if (ret == SOCKET_ERROR ) {
243
- MONGOC_WARNING ("WSAGetLastError(): %d" , WSAGetLastError ());
244
- ret = -1 ;
245
- }
246
- #else
247
299
ret = poll (pfds , nsds , timeout );
248
- #endif
249
-
250
300
for (i = 0 ; i < nsds ; i ++ ) {
251
301
sds [i ].revents = pfds [i ].revents ;
252
302
}
253
303
254
304
bson_free (pfds );
305
+ #endif
255
306
256
307
return ret ;
257
308
}
0 commit comments