Question:
The error below happens randomly, and because of the error type it seems that I can't catch this error on .Net 4.5. I suspect that the bug happens when a connection is dropped while reading. Our process runs on a less than reliable network, with built in retry, but when this error occurs the application just dies. What makes this worse is that it's in an thread and when that thread dies all of the other processes running halt as well.
Ideally I would really just like to be able to gracefully handle the error and push a normalize error up the stack, but I can't do it in this case.
Thoughts?
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at ClsTask.GetResultInt(ClsTask* )
at Chilkat.Task.GetResultInt()
at gsmith.Lib.FTP.<GetFileListAsync>d__1a.MoveNext() in c:\USB\Source\ECommerce\gsmith\gsmith.Lib\FTP.cs:line 297
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run()
at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action action, Boolean allowInlining, Task& currentTask)
at System.Threading.Tasks.Task.FinishContinuations()
at System.Threading.Tasks.Task`1.TrySetResult(TResult result)
at System.Threading.Tasks.Task.DelayPromise.Complete()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.TimerQueueTimer.CallCallback()
at System.Threading.TimerQueueTimer.Fire()
at System.Threading.TimerQueue.FireNextTimers()
Here is the offending method:
public async Task<List<string>> GetFileListAsync(string url, string path, string username, string password, string filter, TimeSpan minAge, CancellationToken ct)
{
try
{
List<string> fileList = new List<string>();
using (Chilkat.Ftp2 ftp = _GetFTPConnection(url, username, password))
{
if (!ftp.ChangeRemoteDir(path))
{
throw new JBApiException(ftp.LastErrorText);
}
Chilkat.Task task = ftp.GetDirCountAsync();
if (task == null)
{
throw new JBApiException(ftp.LastErrorText);
}
if (!task.Run())
{
throw new JBApiException(ftp.LastErrorText);
}
while (!task.Finished && !ct.IsCancellationRequested)
{
//Sleep 100 ms.
await Task.Delay(100, ct);
}
if (!ct.IsCancellationRequested)
{
int n = task.GetResultInt();
if (n > 0)
{
// Loop over the directory contents, incrementing the count
// each time it is NOT a directory.
int fileCount = 0;
for (int i = 0; i <= n - 1; i++)
{
// Is this NOT a sub-directory?
if (!ftp.GetIsDirectory(i))
{
fileCount = fileCount + 1;
fileList.Add(ftp.GetFilename(i));
}
}
System.Diagnostics.Debug.WriteLine(string.Format("Files: {0}", fileList.Count));
}
}
ftp.Disconnect();
return fileList;
}
}
catch (Exception ex)
{
if (!(ex is JBApiException))
{
ex = new JBApiException(ex.Message, ex, false);
}
ex.Data["Url"] = url;
ex.Data["Path"] = path;
ex.Data["Filter"] = filter;
ex.Data["Username"] = username;
ex.Data["Password"] = password;
throw ex;
}
}
I found the code below in the samples. I suspect that I should check TaskSuccess as well before even trying to retrieve the value from the underlying call. Thoughts? (https://www.example-code.com/csharp/async_task.asp)
// If the task "completed", then it ran to completion, but the actual success/failure of the method
// is determined by the result obtained via a GetResult* method. (A "completed" task will
// have a StatusInt equal to 7. If the task finished, but was not completed, then it must've
// been aborted or canceled:
if (task.StatusInt != 7) {
Console.WriteLine("Task did not complete.");
Console.WriteLine("task status: " + task.Status);
return;
}
Thanks Gary. What version of Chilkat are you using? If you're not using the latest, first test with the latest version v9.5.0.56.
If you're already using the latest version of Chilkat, please let me know the .NET Framework so I can provide a new pre-release build of the next version. If it's not already fixed, then we can investigate..
Thanks Gary,
If the stack trace shows the underlying "Cls" Chilkat object, then it's a crash inside the Chilkat lib.
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at ClsTask.GetResultInt(ClsTask* ) ...
I'm going to post the latest v9.5.0.58 pre-release for you to test. If it still has trouble, we'll go from there.
Here's the new build:
32-bit Download: http://www.chilkatsoft.com/download/preRelease/ChilkatDotNet45-9.5.0-win32.zip
64-bit Download: http://www.chilkatsoft.com/download/preRelease/ChilkatDotNet45-9.5.0-x64.zip