Skip to content

Commit 5ee95b8

Browse files
authored
Fix Bug #3410: Fix infinite loop after a failed network connection due to changed curl messaging (#3412)
* Curl 8.14.1 (or maybe earlier) has changed output messaging when curl exceptions are raised. This has caused the curl exception handling / retry handling to fail due to unable to match error log output. * Add an exception fallback to ensure retry interval is enforced in case of unknown CurlException event * Update calculateBackoff() function to prevent integer overflow
1 parent ed4880f commit 5ee95b8

File tree

1 file changed

+27
-7
lines changed

1 file changed

+27
-7
lines changed

src/onedrive.d

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,7 +1714,7 @@ class OneDriveApi {
17141714

17151715
// Detail the curl exception, debug output only
17161716
if (debugLogging) {
1717-
addLogEntry("Handling a specific Curl exception:", ["debug"]);
1717+
addLogEntry("Handling a curl exception:", ["debug"]);
17181718
addLogEntry(to!string(response), ["debug"]);
17191719
}
17201720

@@ -1727,17 +1727,26 @@ class OneDriveApi {
17271727
setFreshConnectOption();
17281728

17291729
// What is contained in the curl error message?
1730-
if (canFind(errorMessage, "Couldn't connect to server on handle") || canFind(errorMessage, "Couldn't resolve host name on handle") || canFind(errorMessage, "Timeout was reached on handle")) {
1730+
// Handle the following:
1731+
// - Couldn't connect to server on handle
1732+
// - Could not connect to server on handle (changed noticed in curl 8.14.1, possibly done earlier ...)
1733+
// - Couldn't resolve host name on handle
1734+
// - Could not resolve host name on handle (changed noticed in curl 8.14.1, possibly done earlier ...)
1735+
// - Timeout was reached on handle
1736+
if (canFind(errorMessage, "connect to server on handle") || canFind(errorMessage, "resolve host name on handle") || canFind(errorMessage, "Timeout was reached on handle")) {
17311737
// Connectivity to Microsoft OneDrive was lost
17321738
addLogEntry("Internet connectivity to Microsoft OneDrive service has been interrupted .. re-trying in the background");
17331739

17341740
// What caused the initial curl exception?
1735-
if (canFind(errorMessage, "Couldn't resolve host name on handle")) {
1741+
// - DNS resolution issue
1742+
if (canFind(errorMessage, "resolve host name on handle")) {
17361743
if (debugLogging) {addLogEntry("Unable to resolve server - DNS access blocked?", ["debug"]);}
17371744
}
1738-
if (canFind(errorMessage, "Couldn't connect to server on handle")) {
1745+
// - connection issue
1746+
if (canFind(errorMessage, "connect to server on handle")) {
17391747
if (debugLogging) {addLogEntry("Unable to connect to server - HTTPS access blocked?", ["debug"]);}
17401748
}
1749+
// - timeout issue
17411750
if (canFind(errorMessage, "Timeout was reached on handle")) {
17421751
// Common cause is libcurl trying IPv6 DNS resolution when there are only IPv4 DNS servers available
17431752
if (verboseLogging) {
@@ -1777,11 +1786,21 @@ class OneDriveApi {
17771786
throw new OneDriveError("Zero disk space detected");
17781787
}
17791788
} else {
1780-
// Unknown error
1789+
// Unknown curl error
17811790
displayGeneralErrorMessage(exception, callingFunction, lineno);
1791+
1792+
// Fallback: Ensure retry interval is enforced in case of unknown CurlException
1793+
if (thisBackOffInterval == 0) {
1794+
thisBackOffInterval = calculateBackoff(retryAttempts, baseBackoffInterval, maxBackoffInterval);
1795+
if (thisBackOffInterval <= 0) {
1796+
thisBackOffInterval = 1;
1797+
addLogEntry("WARNING: Enforcing minimum backoff interval of 1 second – unclassified CurlException");
1798+
}
1799+
}
17821800
}
17831801
}
17841802
}
1803+
17851804
// A OneDrive API exception was thrown
17861805
} catch (OneDriveException exception) {
17871806
// https://developer.overdrive.com/docs/reference-guide
@@ -2011,8 +2030,9 @@ class OneDriveApi {
20112030

20122031
// Calculates the delay for exponential backoff
20132032
private int calculateBackoff(int retryAttempts, int baseInterval, int maxInterval) {
2014-
int backoffTime = min(pow(2, retryAttempts) * baseInterval, maxInterval);
2015-
return backoffTime;
2033+
int cappedAttempts = min(retryAttempts, 10); // Prevent exponent overflow
2034+
int backoff = baseInterval * (1 << cappedAttempts);
2035+
return min(backoff, maxInterval);
20162036
}
20172037

20182038
// Configure libcurl to perform a fresh connection

0 commit comments

Comments
 (0)