Skip to content

Commit a5c0b63

Browse files
committed
Retry poll calls on EINTR
When signals are delievered to the process, calls here to poll may be interrupted and return with a spurious failure. The call instead should be restarted.
1 parent 1dab2c1 commit a5c0b63

File tree

1 file changed

+31
-18
lines changed
  • sdk/core/azure-core/src/http/curl

1 file changed

+31
-18
lines changed

sdk/core/azure-core/src/http/curl/curl.cpp

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// SPDX-License-Identifier: MIT
33

4+
#include "azure/core/platform.hpp"
5+
6+
#if defined(AZ_PLATFORM_WINDOWS)
7+
#if !defined(WIN32_LEAN_AND_MEAN)
8+
#define WIN32_LEAN_AND_MEAN
9+
#endif
10+
#if !defined(NOMINMAX)
11+
#define NOMINMAX
12+
#endif
13+
#endif
14+
415
#include "azure/core/http/curl_transport.hpp"
516
#include "azure/core/http/http.hpp"
617
#include "azure/core/http/policies/policy.hpp"
718
#include "azure/core/http/transport.hpp"
819
#include "azure/core/internal/diagnostics/log.hpp"
9-
#include "azure/core/platform.hpp"
1020

1121
// Private include
1222
#include "curl_connection_pool_private.hpp"
@@ -17,16 +27,11 @@
1727
#include <poll.h> // for poll()
1828
#include <sys/socket.h> // for socket shutdown
1929
#elif defined(AZ_PLATFORM_WINDOWS)
20-
#if !defined(WIN32_LEAN_AND_MEAN)
21-
#define WIN32_LEAN_AND_MEAN
22-
#endif
23-
#if !defined(NOMINMAX)
24-
#define NOMINMAX
25-
#endif
2630
#include <winsock2.h> // for WSAPoll();
2731
#endif
2832

2933
#include <algorithm>
34+
#include <chrono>
3035
#include <string>
3136
#include <thread>
3237

@@ -94,25 +99,33 @@ int pollSocketUntilEventOrTimeout(
9499
// we use 1 as arg.
95100

96101
// Cancelation is possible by calling poll() with small time intervals instead of using the
97-
// requested timeout. Default interval for calling poll() is 1 sec whenever arg timeout is
98-
// greater than 1 sec. Otherwise the interval is set to timeout
99-
long interval = 1000; // 1 second
100-
if (timeout < interval)
101-
{
102-
interval = timeout;
103-
}
102+
// requested timeout. The polling interval is 1 second.
103+
static constexpr std::chrono::milliseconds pollInterval(1000); // 1 second
104104
int result = 0;
105-
for (long counter = 0; counter < timeout && result == 0; counter = counter + interval)
105+
auto now = std::chrono::steady_clock::now();
106+
auto deadline = now + std::chrono::milliseconds(timeout);
107+
while (now < deadline)
106108
{
107109
// check cancelation
108110
context.ThrowIfCancelled();
111+
std::chrono::milliseconds pollTimeout = std::min(
112+
poll_interval, std::chrono::duration_cast<std::chrono::milliseconds>(deadline - now));
109113
#if defined(AZ_PLATFORM_POSIX)
110-
result = poll(&poller, 1, interval);
114+
result = poll(&poller, 1, poll_timeout.count());
115+
if (result < 0 && EINTR == errno)
116+
{
117+
continue;
118+
}
111119
#elif defined(AZ_PLATFORM_WINDOWS)
112-
result = WSAPoll(&poller, 1, interval);
120+
result = WSAPoll(&poller, 1, poll_timeout.count());
113121
#endif
122+
if (result != 0)
123+
{
124+
return result;
125+
}
126+
now = std::chrono::steady_clock::now();
114127
}
115-
// result can be either 0 (timeout) or > 1 (socket ready)
128+
// result can be 0 (timeout), > 0 (socket ready), or < 0 (error)
116129
return result;
117130
}
118131

0 commit comments

Comments
 (0)