Improve exception from SftpClient.BeginDownloadFile
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 4.4k
- Forks
- 993
- Avg merge
- 9d 21h
- Merged PRs (30d)
- 1
Description
I recently ran into an issue using SftpClient.BeginDownloadFile(). It turned out that the asyncCallback function I was passing was throwing an exception, but it was more difficult than anticipated to find the root cause because the exception from my function was caught by BeginDownloadFile(), which then reacts by calling asyncResult.SetAsCompleted(exp, false), which in turn throws an InvalidOperationException because the completion flag was already set before executing my callback function. (The root cause becomes apparent when breaking on first-chance exceptions but I often have that turned off due to nuisances it can create.)
As I see it, a simple thing to do to improve this would be to modify AsyncResult.SetAsCompleted() to set the inner exception (it's already passed the exception causing the completion):
throw new InvalidOperationException("You can set a result only once");
changes to
throw new InvalidOperationException("You can set a result only once", exception);
I don't know what other contexts this may affect, but it seems reasonable....
Another possibility is to break up the try/catch in SftpClient.BeginFileDownload() so asyncResult.SetAsCompleted(exp, false) gets called only if InternalDownloadFile() throws and asyncResult.SetAsCompleted(null, false) gets called otherwise. Something like
bool success = false;
try
{
InternalDownloadFile(path, output, asyncResult, offset =>
{
asyncResult.Update(offset);
if (downloadCallback != null)
{
downloadCallback(offset);
}
});
success = true;
}
catch (Exception exp)
{
asyncResult.SetAsCompleted(exp, false);
}
if (success)
{
asyncResult.SetAsCompleted(null, false);
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with SftpClient.BeginDownloadFile(), InternalDownloadFile(), and AsyncResult.SetAsCompleted() to trace how callback exceptions are caught and completion is marked. Compare the proposed exception-preservation and control-flow approaches; done means the original callback failure remains discoverable instead of being obscured by a second InvalidOperationException.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100