Skip to content

Commit 1346d66

Browse files
committed
Revert "Revert 'multi: implement wait using winsock events'"
This reverts commit 2260e0e, also restoring previous follow up changes which were reverted. Authored-by: rcombs on github Authored-by: Marc Hörsken Restores curl#5634 Reverts curl#6281 Part of curl#6245
1 parent 6d930d7 commit 1346d66

File tree

2 files changed

+153
-3
lines changed

2 files changed

+153
-3
lines changed

lib/multi.c

+149-3
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,11 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
381381
multi->max_concurrent_streams = 100;
382382
multi->ipv6_works = Curl_ipv6works(NULL);
383383

384+
#ifdef USE_WINSOCK
385+
multi->wsa_event = WSACreateEvent();
386+
if(multi->wsa_event == WSA_INVALID_EVENT)
387+
goto error;
388+
#else
384389
#ifdef ENABLE_WAKEUP
385390
if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) {
386391
multi->wakeup_pair[0] = CURL_SOCKET_BAD;
@@ -393,6 +398,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
393398
multi->wakeup_pair[0] = CURL_SOCKET_BAD;
394399
multi->wakeup_pair[1] = CURL_SOCKET_BAD;
395400
}
401+
#endif
396402
#endif
397403

398404
return multi;
@@ -1080,9 +1086,15 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
10801086
unsigned int curlfds;
10811087
long timeout_internal;
10821088
int retcode = 0;
1089+
#ifndef USE_WINSOCK
10831090
struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
10841091
struct pollfd *ufds = &a_few_on_stack[0];
10851092
bool ufds_malloc = FALSE;
1093+
#else
1094+
struct pollfd pre_poll;
1095+
WSANETWORKEVENTS wsa_events;
1096+
DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT);
1097+
#endif
10861098

10871099
if(!GOOD_MULTI_HANDLE(multi))
10881100
return CURLM_BAD_HANDLE;
@@ -1128,11 +1140,16 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
11281140
nfds += extra_nfds; /* add the externally provided ones */
11291141

11301142
#ifdef ENABLE_WAKEUP
1143+
#ifdef USE_WINSOCK
1144+
if(use_wakeup) {
1145+
#else
11311146
if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
1147+
#endif
11321148
++nfds;
11331149
}
11341150
#endif
11351151

1152+
#ifndef USE_WINSOCK
11361153
if(nfds > NUM_POLLS_ON_STACK) {
11371154
/* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes
11381155
big, so at 2^29 sockets this value might wrap. When a process gets
@@ -1143,7 +1160,9 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
11431160
return CURLM_OUT_OF_MEMORY;
11441161
ufds_malloc = TRUE;
11451162
}
1163+
11461164
nfds = 0;
1165+
#endif
11471166

11481167
/* only do the second loop if we found descriptors in the first stage run
11491168
above */
@@ -1156,22 +1175,40 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
11561175

11571176
for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
11581177
curl_socket_t s = CURL_SOCKET_BAD;
1159-
1178+
#ifdef USE_WINSOCK
1179+
long mask = 0;
1180+
#endif
11601181
if(bitmap & GETSOCK_READSOCK(i)) {
1182+
#ifdef USE_WINSOCK
1183+
if(timeout_ms && SOCKET_READABLE(sockbunch[i], 0) > 0)
1184+
timeout_ms = 0;
1185+
mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
1186+
#else
11611187
ufds[nfds].fd = sockbunch[i];
11621188
ufds[nfds].events = POLLIN;
11631189
++nfds;
1190+
#endif
11641191
s = sockbunch[i];
11651192
}
11661193
if(bitmap & GETSOCK_WRITESOCK(i)) {
1194+
#ifdef USE_WINSOCK
1195+
if(timeout_ms && SOCKET_WRITABLE(sockbunch[i], 0) > 0)
1196+
timeout_ms = 0;
1197+
mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
1198+
#else
11671199
ufds[nfds].fd = sockbunch[i];
11681200
ufds[nfds].events = POLLOUT;
11691201
++nfds;
1202+
#endif
11701203
s = sockbunch[i];
11711204
}
11721205
if(s == CURL_SOCKET_BAD) {
11731206
break;
11741207
}
1208+
#ifdef USE_WINSOCK
1209+
if(WSAEventSelect(s, multi->wsa_event, mask) != 0)
1210+
return CURLM_INTERNAL_ERROR;
1211+
#endif
11751212
}
11761213

11771214
data = data->next; /* check next handle */
@@ -1180,6 +1217,37 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
11801217

11811218
/* Add external file descriptions from poll-like struct curl_waitfd */
11821219
for(i = 0; i < extra_nfds; i++) {
1220+
#ifdef USE_WINSOCK
1221+
long mask = 0;
1222+
extra_fds[i].revents = 0;
1223+
pre_poll.fd = extra_fds[i].fd;
1224+
pre_poll.events = 0;
1225+
pre_poll.revents = 0;
1226+
if(extra_fds[i].events & CURL_WAIT_POLLIN) {
1227+
mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
1228+
pre_poll.events |= POLLIN;
1229+
}
1230+
if(extra_fds[i].events & CURL_WAIT_POLLPRI) {
1231+
mask |= FD_OOB;
1232+
pre_poll.events |= POLLPRI;
1233+
}
1234+
if(extra_fds[i].events & CURL_WAIT_POLLOUT) {
1235+
mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
1236+
pre_poll.events |= POLLOUT;
1237+
}
1238+
if(Curl_poll(&pre_poll, 1, 0) > 0) {
1239+
if(pre_poll.revents & POLLIN)
1240+
extra_fds[i].revents |= CURL_WAIT_POLLIN;
1241+
if(pre_poll.revents & POLLPRI)
1242+
extra_fds[i].revents |= CURL_WAIT_POLLPRI;
1243+
if(pre_poll.revents & POLLOUT)
1244+
extra_fds[i].revents |= CURL_WAIT_POLLOUT;
1245+
if(extra_fds[i].revents)
1246+
timeout_ms = 0;
1247+
}
1248+
if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, mask) != 0)
1249+
return CURLM_INTERNAL_ERROR;
1250+
#else
11831251
ufds[nfds].fd = extra_fds[i].fd;
11841252
ufds[nfds].events = 0;
11851253
if(extra_fds[i].events & CURL_WAIT_POLLIN)
@@ -1189,26 +1257,57 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
11891257
if(extra_fds[i].events & CURL_WAIT_POLLOUT)
11901258
ufds[nfds].events |= POLLOUT;
11911259
++nfds;
1260+
#endif
11921261
}
11931262

11941263
#ifdef ENABLE_WAKEUP
1264+
#ifndef USE_WINSOCK
11951265
if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
11961266
ufds[nfds].fd = multi->wakeup_pair[0];
11971267
ufds[nfds].events = POLLIN;
11981268
++nfds;
11991269
}
1270+
#endif
12001271
#endif
12011272

12021273
if(nfds) {
12031274
/* wait... */
1275+
#ifdef USE_WINSOCK
1276+
WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE, timeout_ms, FALSE);
1277+
#else
12041278
int pollrc = Curl_poll(ufds, nfds, timeout_ms);
1279+
#endif
1280+
1281+
#ifdef USE_WINSOCK
1282+
/* With Winsock, we have to run this unconditionally to call
1283+
WSAEventSelect(fd, event, 0) on all the sockets */
1284+
{
1285+
retcode = 0;
1286+
#else
12051287
if(pollrc > 0) {
12061288
retcode = pollrc;
1289+
#endif
12071290
/* copy revents results from the poll to the curl_multi_wait poll
12081291
struct, the bit values of the actual underlying poll() implementation
12091292
may not be the same as the ones in the public libcurl API! */
12101293
for(i = 0; i < extra_nfds; i++) {
12111294
unsigned short mask = 0;
1295+
#ifdef USE_WINSOCK
1296+
wsa_events.lNetworkEvents = 0;
1297+
mask = extra_fds[i].revents;
1298+
if(WSAEnumNetworkEvents(extra_fds[i].fd, multi->wsa_event,
1299+
&wsa_events) == 0) {
1300+
if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE))
1301+
mask |= CURL_WAIT_POLLIN;
1302+
if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE))
1303+
mask |= CURL_WAIT_POLLOUT;
1304+
if(wsa_events.lNetworkEvents & FD_OOB)
1305+
mask |= CURL_WAIT_POLLPRI;
1306+
if(ret && wsa_events.lNetworkEvents != 0)
1307+
retcode++;
1308+
}
1309+
WSAEventSelect(extra_fds[i].fd, multi->wsa_event, 0);
1310+
#else
12121311
unsigned r = ufds[curlfds + i].revents;
12131312

12141313
if(r & POLLIN)
@@ -1217,9 +1316,46 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
12171316
mask |= CURL_WAIT_POLLOUT;
12181317
if(r & POLLPRI)
12191318
mask |= CURL_WAIT_POLLPRI;
1319+
#endif
12201320
extra_fds[i].revents = mask;
12211321
}
12221322

1323+
#ifdef USE_WINSOCK
1324+
/* Count up all our own sockets that had activity,
1325+
and remove them from the event. */
1326+
if(curlfds) {
1327+
data = multi->easyp;
1328+
while(data) {
1329+
bitmap = multi_getsock(data, sockbunch);
1330+
1331+
for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
1332+
if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) {
1333+
wsa_events.lNetworkEvents = 0;
1334+
if(WSAEnumNetworkEvents(sockbunch[i], multi->wsa_event,
1335+
&wsa_events) == 0) {
1336+
if(ret && wsa_events.lNetworkEvents != 0)
1337+
retcode++;
1338+
}
1339+
if(ret && !timeout_ms && wsa_events.lNetworkEvents == 0) {
1340+
if((bitmap & GETSOCK_READSOCK(i)) &&
1341+
SOCKET_READABLE(sockbunch[i], 0) > 0)
1342+
retcode++;
1343+
else if((bitmap & GETSOCK_WRITESOCK(i)) &&
1344+
SOCKET_WRITABLE(sockbunch[i], 0) > 0)
1345+
retcode++;
1346+
}
1347+
WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
1348+
}
1349+
else
1350+
break;
1351+
}
1352+
1353+
data = data->next;
1354+
}
1355+
}
1356+
1357+
WSAResetEvent(multi->wsa_event);
1358+
#else
12231359
#ifdef ENABLE_WAKEUP
12241360
if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
12251361
if(ufds[curlfds + extra_nfds].revents & POLLIN) {
@@ -1232,23 +1368,24 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
12321368
when there is no more data, breaking the loop. */
12331369
nread = sread(multi->wakeup_pair[0], buf, sizeof(buf));
12341370
if(nread <= 0) {
1235-
#ifndef USE_WINSOCK
12361371
if(nread < 0 && EINTR == SOCKERRNO)
12371372
continue;
1238-
#endif
12391373
break;
12401374
}
12411375
}
12421376
/* do not count the wakeup socket into the returned value */
12431377
retcode--;
12441378
}
12451379
}
1380+
#endif
12461381
#endif
12471382
}
12481383
}
12491384

1385+
#ifndef USE_WINSOCK
12501386
if(ufds_malloc)
12511387
free(ufds);
1388+
#endif
12521389
if(ret)
12531390
*ret = retcode;
12541391
if(!extrawait || nfds)
@@ -1303,6 +1440,10 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
13031440
return CURLM_BAD_HANDLE;
13041441

13051442
#ifdef ENABLE_WAKEUP
1443+
#ifdef USE_WINSOCK
1444+
if(WSASetEvent(multi->wsa_event))
1445+
return CURLM_OK;
1446+
#else
13061447
/* the wakeup_pair variable is only written during init and cleanup,
13071448
making it safe to access from another thread after the init part
13081449
and before cleanup */
@@ -1335,6 +1476,7 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
13351476
return CURLM_OK;
13361477
}
13371478
}
1479+
#endif
13381480
#endif
13391481
return CURLM_WAKEUP_FAILURE;
13401482
}
@@ -2478,9 +2620,13 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
24782620
Curl_hash_destroy(&multi->hostcache);
24792621
Curl_psl_destroy(&multi->psl);
24802622

2623+
#ifdef USE_WINSOCK
2624+
WSACloseEvent(multi->wsa_event);
2625+
#else
24812626
#ifdef ENABLE_WAKEUP
24822627
sclose(multi->wakeup_pair[0]);
24832628
sclose(multi->wakeup_pair[1]);
2629+
#endif
24842630
#endif
24852631
free(multi);
24862632

lib/multihandle.h

+4
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,13 @@ struct Curl_multi {
140140
previous callback */
141141
unsigned int max_concurrent_streams;
142142

143+
#ifdef USE_WINSOCK
144+
WSAEVENT wsa_event; /* winsock event used for waits */
145+
#else
143146
#ifdef ENABLE_WAKEUP
144147
curl_socket_t wakeup_pair[2]; /* socketpair() used for wakeup
145148
0 is used for read, 1 is used for write */
149+
#endif
146150
#endif
147151
/* multiplexing wanted */
148152
bool multiplexing;

0 commit comments

Comments
 (0)