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: 2017-04-26 19:01 UTC (History)
4 users (show)

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


Attachments

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.

Note You need to log in before you can comment on or make changes to this bug.