Skip to content

Commit 620b8f1

Browse files
authored
Fix Linux/core2.0-only flakiness (#1305)
1 parent 03d2a2b commit 620b8f1

File tree

2 files changed

+33
-31
lines changed

2 files changed

+33
-31
lines changed

Src/Support/Google.Apis.Auth.Tests/OAuth2/LimitedLocalhostHttpServerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ public async Task Cancellation()
160160
{
161161
var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(100));
162162
await client.ConnectAsync("localhost", server.Port);
163-
var ex = await Assert.ThrowsAsync<OperationCanceledException>(() => server.GetQueryParamsAsync(cts.Token));
163+
await Assert.ThrowsAsync<OperationCanceledException>(() => server.GetQueryParamsAsync(cts.Token));
164164
}
165165
}
166166

Src/Support/Google.Apis.Auth/OAuth2/LocalServerCodeReceiver.cs

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -198,47 +198,49 @@ private LimitedLocalhostHttpServer(TcpListener listener)
198198
private async Task<Dictionary<string, string>> GetQueryParamsFromClientAsync(TcpClient client, CancellationToken cancellationToken)
199199
{
200200
var stream = client.GetStream();
201-
202-
var buffer = new byte[NetworkReadBufferSize];
203-
int bufferOfs = 0;
204-
int bufferSize = 0;
205-
Func<Task<char?>> getChar = async () =>
201+
// NetworkStream.ReadAsync() doesn't honour the cancellation-token (on all platforms),
202+
// so use workaround
203+
using (cancellationToken.Register(() => stream.Dispose()))
206204
{
207-
if (bufferOfs == bufferSize)
205+
var buffer = new byte[NetworkReadBufferSize];
206+
int bufferOfs = 0;
207+
int bufferSize = 0;
208+
Func<Task<char?>> getChar = async () =>
208209
{
209-
// Networkstream.ReadAsync() doesn't honour the cancellation-token, so use workaround
210-
using (cancellationToken.Register(() => stream.Dispose()))
210+
if (bufferOfs == bufferSize)
211211
{
212212
try
213213
{
214214
bufferSize = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
215215
}
216216
// netcoreapp2.x throws an IOException on stream disposal; others throw ObjectDispoesdException
217-
catch (Exception e) when (e is ObjectDisposedException || e is IOException)
217+
catch (Exception e) when (e is ObjectDisposedException || e is IOException)
218218
{
219-
cancellationToken.ThrowIfCancellationRequested();
220-
throw new OperationCanceledException();
219+
throw new OperationCanceledException(cancellationToken);
221220
}
221+
// netcoreapp2.0 on Linux sometimes doesn't throw an exception on stream disposal in ReadAsync,
222+
// so check for cancellation afterwards
223+
cancellationToken.ThrowIfCancellationRequested();
224+
if (bufferSize == 0)
225+
{
226+
// End of stream
227+
return null;
228+
}
229+
bufferOfs = 0;
222230
}
223-
if (bufferSize == 0)
224-
{
225-
// End of stream
226-
return null;
227-
}
228-
bufferOfs = 0;
229-
}
230-
byte b = buffer[bufferOfs++];
231-
// HTTP headers are generally ASCII, but historically allowed ISO-8859-1.
232-
// Non-ASCII bytes should be treated opaquely, not further processed (e.g. as UTF8).
233-
return (char)b;
234-
};
235-
236-
string requestLine = await ReadRequestLine(getChar).ConfigureAwait(false);
237-
var requestParams = ValidateAndGetRequestParams(requestLine);
238-
await WaitForAllHeaders(getChar).ConfigureAwait(false);
239-
await WriteResponse(stream, cancellationToken).ConfigureAwait(false);
240-
241-
return requestParams;
231+
byte b = buffer[bufferOfs++];
232+
// HTTP headers are generally ASCII, but historically allowed ISO-8859-1.
233+
// Non-ASCII bytes should be treated opaquely, not further processed (e.g. as UTF8).
234+
return (char)b;
235+
};
236+
237+
string requestLine = await ReadRequestLine(getChar).ConfigureAwait(false);
238+
var requestParams = ValidateAndGetRequestParams(requestLine);
239+
await WaitForAllHeaders(getChar).ConfigureAwait(false);
240+
await WriteResponse(stream, cancellationToken).ConfigureAwait(false);
241+
242+
return requestParams;
243+
}
242244
}
243245

244246
private async Task<string> ReadRequestLine(Func<Task<char?>> getChar)

0 commit comments

Comments
 (0)