Skip to content

Commit

Permalink
add gradle error handler for when the remote ssl host terminates hand…
Browse files Browse the repository at this point in the history
…shake process (flutter#125270)

Will fix transient network failures as in: flutter#125108 (comment)
  • Loading branch information
christopherfujino authored Apr 21, 2023
1 parent d93ffc1 commit 1561b65
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/flutter_tools/lib/src/android/gradle.dart
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
isBuildingBundle: false,
localGradleErrors: gradleErrors,
configOnly: configOnly,
maxRetries: 1,
);
}

Expand All @@ -227,6 +228,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
validateDeferredComponents: validateDeferredComponents,
deferredComponentsEnabled: deferredComponentsEnabled,
configOnly: configOnly,
maxRetries: 1,
);
}

Expand Down
20 changes: 20 additions & 0 deletions packages/flutter_tools/lib/src/android/gradle_errors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ final List<GradleHandledError> gradleErrors = <GradleHandledError>[
sslExceptionHandler,
zipExceptionHandler,
incompatibleJavaAndGradleVersionsHandler,
remoteTerminatedHandshakeHandler,
];

const String _boxTitle = 'Flutter Fix';
Expand Down Expand Up @@ -700,3 +701,22 @@ final GradleHandledError incompatibleJavaAndGradleVersionsHandler = GradleHandle
},
eventLabel: 'incompatible-java-gradle-version',
);

@visibleForTesting
final GradleHandledError remoteTerminatedHandshakeHandler = GradleHandledError(
test: (String line) => line.contains('Remote host terminated the handshake'),
handler: ({
required String line,
required FlutterProject project,
required bool usesAndroidX,
required bool multidexEnabled,
}) async {
globals.printError(
'${globals.logger.terminal.warningMark} '
'Gradle threw an error while downloading artifacts from the network.'
);

return GradleBuildStatus.retry;
},
eventLabel: 'remote-terminated-handshake',
);
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ void main() {
sslExceptionHandler,
zipExceptionHandler,
incompatibleJavaAndGradleVersionsHandler,
remoteTerminatedHandshakeHandler,
])
);
});
Expand Down Expand Up @@ -88,6 +89,50 @@ at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)''';
ProcessManager: () => processManager,
});

testUsingContext('retries if remote host terminated ssl handshake', () async {
const String errorMessage = r'''
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
at java.base/sun.security.ssl.SSLSocketImpl.handleEOF(SSLSocketImpl.java:1696)
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1514)
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1416)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:456)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:427)
at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:572)
at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:197)
at java.base/sun.net.www.protocol.http.HttpURLConnection.followRedirect0(HttpURLConnection.java:2783)
at java.base/sun.net.www.protocol.http.HttpURLConnection.followRedirect(HttpURLConnection.java:2695)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1854)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1520)
at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:250)
at org.gradle.wrapper.Download.downloadInternal(Download.java:58)
at org.gradle.wrapper.Download.download(Download.java:44)
at org.gradle.wrapper.Install$1.call(Install.java:61)
at org.gradle.wrapper.Install$1.call(Install.java:48)
at org.gradle.wrapper.ExclusiveFileAccessManager.access(ExclusiveFileAccessManager.java:65)
at org.gradle.wrapper.Install.createDist(Install.java:48)
at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:128)
at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at java.base/sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:483)
at java.base/sun.security.ssl.SSLSocketInputRecord.readHeader(SSLSocketInputRecord.java:472)
at java.base/sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:160)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:111)
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1506)''';

expect(formatTestErrorMessage(errorMessage, remoteTerminatedHandshakeHandler), isTrue);
expect(await remoteTerminatedHandshakeHandler.handler(
line: '',
multidexEnabled: true,
project: FakeFlutterProject(),
usesAndroidX: true,
), equals(GradleBuildStatus.retry));

expect(testLogger.errorText,
contains(
'Gradle threw an error while downloading artifacts from the network.'
)
);
});
testUsingContext('retries if gradle fails downloading with proxy error', () async {
const String errorMessage = r'''
Exception in thread "main" java.io.IOException: Unable to tunnel through proxy. Proxy returns "HTTP/1.1 400 Bad Request"
Expand Down

0 comments on commit 1561b65

Please sign in to comment.