Bug 12300 - FtpWebRequest - Request aborted exception
Summary: FtpWebRequest - Request aborted exception
Status: NEW
Alias: None
Product: Class Libraries
Classification: Mono
Component: System.Web (show other bugs)
Version: 2.10.x
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2013-05-19 19:21 UTC by refusebin.mail
Modified: 2018-01-22 15:25 UTC (History)
5 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report for Bug 12300 on GitHub or Developer Community if you have new information to add and do not yet see a matching new report.

If the latest results still closely match this report, you can use the original description:

  • Export the original title and description: GitHub Markdown or Developer Community HTML
  • Copy the title and description into the new report. Adjust them to be up-to-date if needed.
  • Add your new information.

In special cases on GitHub you might also want the comments: GitHub Markdown with public comments

Related Links:
Status:
NEW

Description refusebin.mail 2013-05-19 19:21:00 UTC
I need to check FTP server availability.
I wrote property 'IsFtpAvailable' for my own 'ClientFTP' class:

        public bool IsFtpAvaliable
        {
            get
            {
                FtpWebRequest request = null;
                FtpWebResponse response = null;
                try
                {
                    request = WebRequest.Create(this.ftpDirectory) as FtpWebRequest;
                    request.Method = WebRequestMethods.Ftp.ListDirectory;
                    request.Credentials = new NetworkCredential(this.userName, this.password);
                    request.KeepAlive = false;
                    request.Timeout = 2000;
                    response = request.GetResponse() as FtpWebResponse;
                    return true;
                }
                catch
                {
                    return false;
                }
                finally
                {
                    if (response != null)
                    {
                        response.Close();
                        response.Dispose();
                    }
                    if (request != null)
                        request = null;
                    GC.Collect();
                }
            }
        }

I use this property in class constructor:

        public ClientFTP(string host, string userName, string password)
        {
            this.host = host;
            this.userName = userName;
            this.password = password;
            this.ftpDirectory = String.Concat("ftp://", this.host);
            this.fileSize = -1;
            if (!this.IsFtpAvaliable) 
                throw new FtpServerUnavailableException("Server unavailable");
        }

If server is unavailable, custom exception is thrown to prevent from creating instance of this class and calling other methods.
Everything works fine, but when ftp server is not avaliable, about one minute after checking availability, I get unhandled exception from FtpWebRequest class ("Request aborted"):

at System.Net.FtpWebRequest.CheckIfAborted () [0x0000c] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/FtpWebRequest.cs:1190 
  at System.Net.FtpWebRequest.set_State (RequestState value) [0x00011] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/FtpWebRequest.cs:356 
  at System.Net.FtpWebRequest.ProcessRequest () [0x00058] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/FtpWebRequest.cs:516 
  at System.Threading.Thread.StartInternal () [0x0001d] in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System.Threading/Thread.cs:697

Belowed method (from FtpWebRequest) is exactly where the exeption is thrown:

        internal void CheckIfAborted () {
            if (State == RequestState.Aborted 
                        throw new WebException ("Request aborted", WebExceptionStatus.RequestCanceled);
        }

The same property (IsFtpAvailable) without timeout specified - works fine.
I think that it must be a bug.
Comment 1 Kris Rusocki 2013-07-11 02:57:05 UTC
Looks like a bug to me as well -- posted my analysis on stackoverflow: http://stackoverflow.com/a/17586430/2571365
Comment 3 tekHedd 2017-04-26 16:33:50 UTC
I have this problem on site with mono 4.8.1 (official) and the FTPS client. After timeout, it crashes the program hard with no option to catch the exception. The program is a service ultimately run from the mono_service helper.

The program does not crash under the .NET runtime.

Stack ends with unhandled exception: 

system.Net.WebException: Request aborted
 CheckIfAborted
 set_State
 ProcesRequest
 ...
 System.Threading.ThreadHelper.ThreadStart

(Sorry, only have screen caps from a multi-remote sesssion. :)

My connection is configured thusly:
   _request.ReadWriteTimeout = 30000;
   _request.Timeout = 30000;
   _request.Credentials = _credentials;
   _request.UsePassive = true;
   _request.UseBinary = true;
   _request.EnableSsl = _useSsl; // true or false depending
   _request.KeepAlive = true;

I will post a workaround if I find one.
Comment 4 tekHedd 2017-04-26 19:01:07 UTC
My attempts to find a workaround have failed. 

Aborting the socket manually does not cancel the underlying socket timeout and uncaught exception.

Async has the same issue. Using GetRequestStreamAsync, then task.Wait(timeout) seems to work, but then later the underlying stream times out with its timeout and shuts down the runtime. 

Setting the timeout to infinite (-1) just results in a crash later when the underlying socket or network layer times out.

In every case, the code *seems* to work, and then later crashes when the underlying socket timeout is reached. This makes testing time consuming.