|
14 | 14 | #include "curl_session_private.hpp"
|
15 | 15 |
|
16 | 16 | #if defined(AZ_PLATFORM_POSIX)
|
| 17 | +#include <chrono> |
17 | 18 | #include <poll.h> // for poll()
|
18 | 19 | #include <sys/socket.h> // for socket shutdown
|
19 | 20 | #elif defined(AZ_PLATFORM_WINDOWS)
|
@@ -102,17 +103,38 @@ int pollSocketUntilEventOrTimeout(
|
102 | 103 | interval = timeout;
|
103 | 104 | }
|
104 | 105 | int result = 0;
|
105 |
| - for (long counter = 0; counter < timeout && result == 0; counter = counter + interval) |
| 106 | + bool poll_interrupted = false; // deadline and now are only valid if poll_interrupted |
| 107 | + long deadline{}; |
| 108 | + long now{}; |
| 109 | + for (long counter = 0; (poll_interrupted ? now < deadline : counter < timeout) && result == 0; |
| 110 | + counter = counter + interval) |
106 | 111 | {
|
107 | 112 | // check cancelation
|
108 | 113 | context.ThrowIfCancelled();
|
109 | 114 | #if defined(AZ_PLATFORM_POSIX)
|
110 | 115 | result = poll(&poller, 1, interval);
|
| 116 | + if (result < 0 && EINTR == errno) |
| 117 | + { |
| 118 | + // Only make extra syscalls to get the time in the (rare) event that poll |
| 119 | + // is interrupted. We jump through these hoops because the poll call does |
| 120 | + // not tell us how long it waited before being interrupted. For the first |
| 121 | + // interruption only, assume no time has passed during the interrupted |
| 122 | + // call. |
| 123 | + now = std::chrono::duration_cast<std::chrono::milliseconds>( |
| 124 | + std::chrono::steady_clock::now().time_since_epoch()) |
| 125 | + .count(); |
| 126 | + if (!poll_interrupted) |
| 127 | + { |
| 128 | + poll_interrupted = true; |
| 129 | + deadline = now + timeout - counter; |
| 130 | + result = 0; |
| 131 | + } |
| 132 | + } |
111 | 133 | #elif defined(AZ_PLATFORM_WINDOWS)
|
112 | 134 | result = WSAPoll(&poller, 1, interval);
|
113 | 135 | #endif
|
114 | 136 | }
|
115 |
| - // result can be either 0 (timeout) or > 1 (socket ready) |
| 137 | + // result can be 0 (timeout), > 0 (socket ready), or < 0 (error) |
116 | 138 | return result;
|
117 | 139 | }
|
118 | 140 |
|
|
0 commit comments