summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2023-02-19 11:03:21 +0100
committerDaniel Stenberg <daniel@haxx.se>2023-02-20 08:11:49 +0100
commita6506f266c386f5c3229e414b36546ace97003cc (patch)
tree0cca5fbba5df7cddcdaf4aeb62b6d764b33b39dd /lib
parent41dfb7f516c8a9659782df695528c9d32b5653d6 (diff)
downloadcurl-a6506f266c386f5c3229e414b36546ace97003cc.tar.gz
socketpair: allow EWOULDBLOCK when reading the pair check bytes
Reported-by: Gunamoi Software Co-authored-by: Jay Satiro Fixes #10561 Closes #10562
Diffstat (limited to 'lib')
-rw-r--r--lib/socketpair.c61
1 files changed, 56 insertions, 5 deletions
diff --git a/lib/socketpair.c b/lib/socketpair.c
index f814146ad..b94c9843e 100644
--- a/lib/socketpair.c
+++ b/lib/socketpair.c
@@ -85,9 +85,22 @@ int Curl_socketpair(int domain, int type, int protocol,
socks[0] = socks[1] = CURL_SOCKET_BAD;
+#if defined(WIN32) || defined(__CYGWIN__)
+ /* don't set SO_REUSEADDR on Windows */
+ (void)reuse;
+#ifdef SO_EXCLUSIVEADDRUSE
+ {
+ int exclusive = 1;
+ if(setsockopt(listener, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
+ (char *)&exclusive, (curl_socklen_t)sizeof(exclusive)) == -1)
+ goto error;
+ }
+#endif
+#else
if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR,
(char *)&reuse, (curl_socklen_t)sizeof(reuse)) == -1)
goto error;
+#endif
if(bind(listener, &a.addr, sizeof(a.inaddr)) == -1)
goto error;
if(getsockname(listener, &a.addr, &addrlen) == -1 ||
@@ -113,14 +126,52 @@ int Curl_socketpair(int domain, int type, int protocol,
goto error;
else {
struct curltime check;
- struct curltime now = Curl_now();
+ struct curltime start = Curl_now();
+ char *p = (char *)&check;
+ size_t s = sizeof(check);
/* write data to the socket */
- swrite(socks[0], &now, sizeof(now));
+ swrite(socks[0], &start, sizeof(start));
/* verify that we read the correct data */
- if((sizeof(now) != sread(socks[1], &check, sizeof(check)) ||
- memcmp(&now, &check, sizeof(check))))
- goto error;
+ do {
+ ssize_t nread;
+
+ pfd[0].fd = socks[1];
+ pfd[0].events = POLLIN;
+ pfd[0].revents = 0;
+ (void)Curl_poll(pfd, 1, 1000); /* one second */
+
+ nread = sread(socks[1], p, s);
+ if(nread == -1) {
+ int sockerr = SOCKERRNO;
+ /* Don't block forever */
+ if(Curl_timediff(Curl_now(), start) > (60 * 1000))
+ goto error;
+ if(
+#ifdef WSAEWOULDBLOCK
+ /* This is how Windows does it */
+ (WSAEWOULDBLOCK == sockerr)
+#else
+ /* errno may be EWOULDBLOCK or on some systems EAGAIN when it
+ returned due to its inability to send off data without
+ blocking. We therefore treat both error codes the same here */
+ (EWOULDBLOCK == sockerr) || (EAGAIN == sockerr) ||
+ (EINTR == sockerr) || (EINPROGRESS == sockerr)
+#endif
+ ) {
+ continue;
+ }
+ goto error;
+ }
+ s -= nread;
+ if(s) {
+ p += nread;
+ continue;
+ }
+ if(memcmp(&start, &check, sizeof(check)))
+ goto error;
+ break;
+ } while(1);
}
sclose(listener);