Skip to content

Commit

Permalink
Added .ConfigureAwait(false) to each await (#525)
Browse files Browse the repository at this point in the history
* Added .ConfigureAwait(false) to each await
- to prevent deadlocks, every await must be paired with .ConfigureAwait(false)
- this is especially important when puppeteer is called from context which must wait for the task synchronously, e.g. using .GetAwaiter.GetResult() or .Task property

- for more info about this topic check https://msdn.microsoft.com/en-us/magazine/jj991977.aspx?f=255&MSPPError=-2147217396

* Fixed awaiting on a task that was obtained using Delegate.DynamicInvoke()
  • Loading branch information
xMarkos authored and kblok committed Aug 3, 2018
1 parent 1f0ecbf commit f8b5ff5
Show file tree
Hide file tree
Showing 27 changed files with 274 additions and 275 deletions.
24 changes: 12 additions & 12 deletions lib/PuppeteerSharp/Browser.cs 100644 → 100755
Expand Up @@ -141,11 +141,11 @@ public async Task<Page> NewPageAsync()
string targetId = (await Connection.SendAsync("Target.createTarget", new Dictionary<string, object>
{
["url"] = "about:blank"
})).targetId.ToString();
}).ConfigureAwait(false)).targetId.ToString();

var target = TargetsMap[targetId];
await target.InitializedTask;
return await target.PageAsync();
await target.InitializedTask.ConfigureAwait(false);
return await target.PageAsync().ConfigureAwait(false);
}

/// <summary>
Expand All @@ -159,7 +159,7 @@ public async Task<Page> NewPageAsync()
/// </summary>
/// <returns>Task which resolves to an array of all open pages.</returns>
public async Task<Page[]> PagesAsync()
=> (await Task.WhenAll(Targets().Select(target => target.PageAsync()))).Where(x => x != null).ToArray();
=> (await Task.WhenAll(Targets().Select(target => target.PageAsync())).ConfigureAwait(false)).Where(x => x != null).ToArray();

/// <summary>
/// Gets the browser's version
Expand All @@ -170,7 +170,7 @@ public async Task<Page[]> PagesAsync()
/// </remarks>
public async Task<string> GetVersionAsync()
{
dynamic version = await Connection.SendAsync("Browser.getVersion");
dynamic version = await Connection.SendAsync("Browser.getVersion").ConfigureAwait(false);
return version.product.ToString();
}

Expand All @@ -183,7 +183,7 @@ public async Task<string> GetVersionAsync()
/// </remarks>
public async Task<string> GetUserAgentAsync()
{
dynamic version = await Connection.SendAsync("Browser.getVersion");
dynamic version = await Connection.SendAsync("Browser.getVersion").ConfigureAwait(false);
return version.userAgent.ToString();
}

Expand All @@ -210,7 +210,7 @@ public async Task CloseAsync()

if (closeTask != null)
{
await closeTask;
await closeTask.ConfigureAwait(false);
}

Disconnect();
Expand All @@ -231,11 +231,11 @@ private async void Connect_MessageReceived(object sender, MessageEventArgs e)
switch (e.MessageID)
{
case "Target.targetCreated":
await CreateTargetAsync(e.MessageData.ToObject<TargetCreatedResponse>());
await CreateTargetAsync(e.MessageData.ToObject<TargetCreatedResponse>()).ConfigureAwait(false);
return;

case "Target.targetDestroyed":
await DestroyTargetAsync(e.MessageData.ToObject<TargetDestroyedResponse>());
await DestroyTargetAsync(e.MessageData.ToObject<TargetDestroyedResponse>()).ConfigureAwait(false);
return;

case "Target.targetInfoChanged":
Expand Down Expand Up @@ -267,7 +267,7 @@ private async Task DestroyTargetAsync(TargetDestroyedResponse e)

target.CloseTaskWrapper.TrySetResult(true);

if (await target.InitializedTask)
if (await target.InitializedTask.ConfigureAwait(false))
{
TargetDestroyed?.Invoke(this, new TargetChangedArgs
{
Expand All @@ -290,7 +290,7 @@ private async Task CreateTargetAsync(TargetCreatedResponse e)

TargetsMap[e.TargetInfo.TargetId] = target;

if (await target.InitializedTask)
if (await target.InitializedTask.ConfigureAwait(false))
{
TargetCreated?.Invoke(this, new TargetChangedArgs
{
Expand All @@ -309,7 +309,7 @@ private async Task CreateTargetAsync(TargetCreatedResponse e)
await connection.SendAsync("Target.setDiscoverTargets", new
{
discover = true
});
}).ConfigureAwait(false);

return browser;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/PuppeteerSharp/BrowserFetcher.cs 100644 → 100755
Expand Up @@ -97,7 +97,7 @@ public async Task<bool> CanDownloadAsync(int revision)
{
RequestUri = new Uri(url),
Method = HttpMethod.Head
});
}).ConfigureAwait(false);

return response.IsSuccessStatusCode;
}
Expand Down Expand Up @@ -179,7 +179,7 @@ public async Task<RevisionInfo> DownloadAsync(int revision)
{
webClient.DownloadProgressChanged += DownloadProgressChanged;
}
await webClient.DownloadFileTaskAsync(new Uri(url), zipPath);
await webClient.DownloadFileTaskAsync(new Uri(url), zipPath).ConfigureAwait(false);

if (Platform == Platform.MacOS)
{
Expand Down
6 changes: 3 additions & 3 deletions lib/PuppeteerSharp/CDPSession.cs 100644 → 100755
Expand Up @@ -86,7 +86,7 @@ internal CDPSession(Connection connection, string targetId, string sessionId)

internal async Task<T> SendAsync<T>(string method, dynamic args = null)
{
var content = await SendAsync(method, true, args);
var content = await SendAsync(method, true, args).ConfigureAwait(false);
return JsonConvert.DeserializeObject<T>(content);
}

Expand Down Expand Up @@ -125,7 +125,7 @@ internal async Task<dynamic> SendAsync(string method, bool rawContent, dynamic a
{
{"sessionId", SessionId},
{"message", message}
});
}).ConfigureAwait(false);
}
catch (Exception ex)
{
Expand All @@ -136,7 +136,7 @@ internal async Task<dynamic> SendAsync(string method, bool rawContent, dynamic a
}
}

return await callback.TaskWrapper.Task;
return await callback.TaskWrapper.Task.ConfigureAwait(false);
}

/// <summary>
Expand Down
10 changes: 5 additions & 5 deletions lib/PuppeteerSharp/Connection.cs 100644 → 100755
Expand Up @@ -101,19 +101,19 @@ internal async Task<dynamic> SendAsync(string method, dynamic args = null)

var encoded = Encoding.UTF8.GetBytes(message);
var buffer = new ArraySegment<byte>(encoded, 0, encoded.Length);
await _socketQueue.Enqueue(() => WebSocket.SendAsync(buffer, WebSocketMessageType.Text, true, default));
await _socketQueue.Enqueue(() => WebSocket.SendAsync(buffer, WebSocketMessageType.Text, true, default)).ConfigureAwait(false);

if (method == CloseMessage)
{
StopReading();
}

return await _responses[id].TaskWrapper.Task;
return await _responses[id].TaskWrapper.Task.ConfigureAwait(false);
}

internal async Task<CDPSession> CreateSessionAsync(string targetId)
{
string sessionId = (await SendAsync("Target.attachToTarget", new { targetId })).sessionId;
string sessionId = (await SendAsync("Target.attachToTarget", new { targetId }).ConfigureAwait(false)).sessionId;
var session = new CDPSession(this, targetId, sessionId);
_sessions.Add(sessionId, session);
return session;
Expand Down Expand Up @@ -176,7 +176,7 @@ private async Task<object> GetResponseAsync()
{
result = await WebSocket.ReceiveAsync(
new ArraySegment<byte>(buffer),
_websocketReaderCancellationSource.Token);
_websocketReaderCancellationSource.Token).ConfigureAwait(false);
}
catch (Exception) when (_stopReading)
{
Expand Down Expand Up @@ -212,7 +212,7 @@ private async Task<object> GetResponseAsync()
{
if (Delay > 0)
{
await Task.Delay(Delay);
await Task.Delay(Delay).ConfigureAwait(false);
}

ProcessResponse(response);
Expand Down
8 changes: 4 additions & 4 deletions lib/PuppeteerSharp/Dialog.cs 100644 → 100755
Expand Up @@ -56,9 +56,9 @@ public Dialog(CDPSession client, DialogType type, string message, string default
/// </summary>
/// <returns>Task which resolves when the dialog has been accepted.</returns>
/// <param name="promptText">A text to enter in prompt. Does not cause any effects if the dialog's type is not prompt.</param>
public async Task Accept(string promptText = "")
public Task Accept(string promptText = "")
{
await _client.SendAsync("Page.handleJavaScriptDialog", new Dictionary<string, object>
return _client.SendAsync("Page.handleJavaScriptDialog", new Dictionary<string, object>
{
{"accept", true},
{"promptText", promptText}
Expand All @@ -69,9 +69,9 @@ public async Task Accept(string promptText = "")
/// Dismiss the dialog.
/// </summary>
/// <returns>Task which resolves when the dialog has been dismissed.</returns>
public async Task Dismiss()
public Task Dismiss()
{
await _client.SendAsync("Page.handleJavaScriptDialog", new Dictionary<string, object>
return _client.SendAsync("Page.handleJavaScriptDialog", new Dictionary<string, object>
{
{"accept", false}
});
Expand Down

0 comments on commit f8b5ff5

Please sign in to comment.