Quantcast
Channel: ASPNETWebStack Issue Tracker Rss Feed
Viewing all articles
Browse latest Browse all 7215

Closed Issue: ReadAsMultipartAsync returns result before all files have been written [282]

$
0
0
We trying to perform validation of the files which have been processed by ReadAsMultipartAsync, but sometimes on the attempts to open file for reading IOException is throwing, like this:

The process cannot access the file 'C:\\Windows\\TEMP\\BodyPart_abd1efe9-b1d5-4956-b79b-0519837e9377' because it is being used by another process.","StackTrace":" at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
at System.IO.File.OpenRead(String path)

at ...

at System.ComponentModel.DataAnnotations.ValidationAttribute.GetValidationResult(Object value, ValidationContext validationContext)
at System.Web.Http.Validation.Validators.DataAnnotationsModelValidator.Validate(ModelMetadata metadata, Object container)
at System.Web.Http.Validation.DefaultBodyModelValidator.ShallowValidate(ModelMetadata metadata, ValidationContext validationContext, Object container)
at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(ModelMetadata metadata, ValidationContext validationContext)
at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container)
at System.Web.Http.ModelBinding.FormatterParameterBinding.<>c__DisplayClass1.<ExecuteBindingAsync>b__0(Object model)
at System.Threading.Tasks.TaskHelpersExtensions.<>c__DisplayClass40.<ToAsyncVoidTask>b__3f()
at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)

Example code:

var provider = new MultipartFormDataStreamProvider(_uploadPath);
return content.ReadAsMultipartAsync(provider)
.ContinueWith(multiPartTask =>
{
if (multiPartTask.IsCanceled || multiPartTask.IsFaulted)
{
Trace.TraceError("Failed multipart message reading: {0}", multiPartTask.Exception);
return null;
}

// ...
// use files in the task Result
// using (var fileStream = File.OpenRead(fileName)) {}

return null;
});

When processing time is delayed by something, eg Thread.Sleep, count of the io exceptions decreased, but it's not workaround.
How can we get access to the files, when it's actually written?

Comments: We are closing this issue because the root cause was found to be in framework code. A separate bug has been opened against an external partner team, and this issue will be tracked there. The changeset: http://aspnetwebstack.codeplex.com/SourceControl/changeset/changes/452b8e1dfa40 reverts an attempted fix where we used FileOptions.WriteThrough to ensure it was not a race between the File Cache and FileStream code. But WriteThrough did not address the core bug and caused a performance degradation. Impact on user code is this: if you upload a file with MultipartFormDataContent and read it on the server using MultiPartDataStreamProvider, the underlying file on the server may not be fully closed after the ReadAsMultipartAsync completes. There is a small window where native code may still be releasing file resources on another thread. The impact is that a File.Delete or File.OpenRead done on that file immediately after the async read may fail with an IOException ("file is in use by another process"). We observed about 0.3% failure rate in high-load situations. The only known work-around is to put a try/catch around those operations, delay a short time if an IOException occurs, and retry. A 50ms delay generally works, but allowing for multiple retries is recommended. This allows the native thread to finish releasing its resources. In our stress labs, this catch-delay-and-retry algorithm always succeeds. See: https://aspnetwebstack.codeplex.com/workitem/176

Viewing all articles
Browse latest Browse all 7215

Trending Articles