1

I am awaiting a call to Amazon.S3.AmazonS3Client.UploadPartAsync but the await never resolves even though I am sure that the request has been fulfilled.

        private async Task<Amazon.S3.Model.UploadPartResponse> UploadPartString(Amazon.S3.AmazonS3Client client, Amazon.S3.Model.InitiateMultipartUploadResponse initiateMultipartUploadResponse, int partNumber, string content)
        {
            Amazon.S3.Model.UploadPartResponse result;
            var length = content.Length * sizeof(Char);
            this.LambdaContext.Logger.LogLine($"Uploading to {initiateMultipartUploadResponse.BucketName}:{initiateMultipartUploadResponse.Key}[{partNumber}]({length + " bytes"})");

            using (var stream = GenerateStreamFromString(content))
            {
                // THIS AWAIT does not resolve
                result = await client.UploadPartAsync(new Amazon.S3.Model.UploadPartRequest()
                {
                    BucketName = initiateMultipartUploadResponse.BucketName,
                    Key = initiateMultipartUploadResponse.Key,
                    PartNumber = partNumber,
                    UploadId = initiateMultipartUploadResponse.UploadId,
                    InputStream = stream,
                    PartSize = 5 * (long)Math.Pow(2, 20),
                });

                // a breakpoint here never fires
                ETags.Add(new Amazon.S3.Model.PartETag(partNumber, result.ETag));
            }

            return result;

        }

A breakpoint after the await never gets hit. I can see a list of 200 OK responses in fiddler though so the requests are working:

fiddler

the calling code for this can be simplified to:

var uploadTasks = new List<Task>();

foreach(var batchString in batches)
{
    uploadTasks.Add(UploadPartString(client, multipartUploadInitiateResult, partIndex, batchString));
}

Task.WaitAll(uploadTasks.ToArray());

My calling code does not ever progress past the Task.WaitAll();

I'm using

  • AWSSDK.Core 3.7.0.17 (latest stable)
  • AWSSDK.S3 3.7.0.18 (latest stable)
Craig
  • 474
  • 7
  • 21
  • 1
    Does the calling code run on a UI thread? I suspect it does, and the fact that `WaitAll` is blocking means you've hit the classic async/sync deadlock situation. There are tons of articles about this, but the gist is that the continuation -- the bit of code after the await -- has been sent for the UI thread to execute, but the UI thread is stuck on the `WaitAll` call and can't execute it, and because of that the `WaitAll` will never complete either, and you've got a deadlock. Use `await Task.WhenAll` instead, and always avoid synchronously waiting for an async operation – canton7 Apr 30 '21 at 08:43
  • @canton7 no, this is a lambda function with no UI. The calling code is the FunctionHandler as defined by the AWS lambda project template and is not async, so I can't await within it. – Craig Apr 30 '21 at 08:45
  • 2
    https://docs.aws.amazon.com/lambda/latest/dg/csharp-handler.html#csharp-handler-async ? Your symptoms are consistent with the deadlock case I described: it's worth eliminating. One way to test is to breakpoint the foreach loop and check whether `SynchronizationContext.Current` is null – canton7 Apr 30 '21 at 08:47
  • 1
    @canton7 yep you're completely correct. I changed the function handler to have an async signature and used WhenAll and it's now working. Thank you! – Craig Apr 30 '21 at 08:52

0 Answers0