Bläddra i källkod

Bug 1619: Failure when .NET assembly starts reading an XML log file in a short moment when it's empty yet

https://winscp.net/tracker/1619

(cherry picked from commit 956ca5bfe897fa4b272152387d2d7b00d82450e4)

+ Adding forgotten implementation of PatientFileStream.Close method (should have been in 956ca5bfe8)

(cherry picked from commit 436f40124bb2dda66762ce04f40dc336f9c5a718)

Source commit: 05f4a019c93d4aef4a0bc8edd6e903db9e923a2e
Martin Prikryl 7 år sedan
förälder
incheckning
74931e150c
1 ändrade filer med 119 tillägg och 12 borttagningar
  1. 119 12
      dotnet/internal/PatientFileStream.cs

+ 119 - 12
dotnet/internal/PatientFileStream.cs

@@ -2,31 +2,38 @@
 
 
 namespace WinSCP
 namespace WinSCP
 {
 {
-    internal class PatientFileStream : FileStream
+    internal class PatientFileStream : Stream
     {
     {
-        public PatientFileStream(Session session, string path, FileMode mode, FileAccess access, FileShare share) :
-            base(path, mode, access, share)
+        public PatientFileStream(Session session, string path, FileMode mode, FileAccess access, FileShare share)
         {
         {
+            _stream = new FileStream(path, mode, access, share);
             _session = session;
             _session = session;
         }
         }
 
 
+        override public void Close()
+        {
+            if (_stream != null)
+            {
+                _stream.Close();
+                _stream = null;
+            }
+
+            base.Close();
+        }
+
+        private const int InitialInterval = 50;
+
         public override int Read(byte[] array, int offset, int count)
         public override int Read(byte[] array, int offset, int count)
         {
         {
             int result;
             int result;
 
 
-            int interval = 50;
+            int interval = InitialInterval;
             do
             do
             {
             {
-                result = base.Read(array, offset, count);
+                result = _stream.Read(array, offset, count);
                 if (result == 0)
                 if (result == 0)
                 {
                 {
-                    _session.Logger.WriteLine("Waiting for log update and dispatching events for {0}", interval);
-                    _session.DispatchEvents(interval);
-                    _session.CheckForTimeout();
-                    if (interval < 500)
-                    {
-                        interval *= 2;
-                    }
+                    Wait(ref interval);
                 }
                 }
             }
             }
             // We always want to return something.
             // We always want to return something.
@@ -37,6 +44,106 @@ namespace WinSCP
             return result;
             return result;
         }
         }
 
 
+        private void Wait(ref int interval)
+        {
+            _session.Logger.WriteLine("Waiting for log update and dispatching events for {0}", interval);
+            _session.DispatchEvents(interval);
+            _session.CheckForTimeout();
+            if (interval < 500)
+            {
+                interval *= 2;
+            }
+        }
+
+        public override void Flush()
+        {
+            throw _session.Logger.WriteException(new System.NotImplementedException());
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            throw _session.Logger.WriteException(new System.NotImplementedException());
+        }
+
+        public override void SetLength(long value)
+        {
+            throw _session.Logger.WriteException(new System.NotImplementedException());
+        }
+
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            throw _session.Logger.WriteException(new System.NotImplementedException());
+        }
+
+        public override bool CanRead
+        {
+            get
+            {
+                bool result = _stream.CanRead;
+                _session.Logger.WriteLineLevel(2, "Can read = {0}", result);
+                return result;
+            }
+        }
+
+        public override bool CanSeek
+        {
+            get
+            {
+                bool result = _stream.CanSeek;
+                _session.Logger.WriteLineLevel(2, "Can seek = {0}", result);
+                return result;
+            }
+        }
+
+        public override bool CanWrite => false;
+
+        public override long Length
+        {
+            get
+            {
+                long result = _stream.Length;
+
+                if (result == 0)
+                {
+                    _session.Logger.WriteLineLevel(2, "File is empty yet, waiting", result);
+
+                    int interval = InitialInterval;
+                    do
+                    {
+                        result = _stream.Length;
+                        if (result == 0)
+                        {
+                            Wait(ref interval);
+                        }
+                        else
+                        {
+                            _session.Logger.WriteLineLevel(2, "File length = {0}", result);
+                        }
+                    }
+                    while (result == 0);
+                }
+
+                return result;
+            }
+        }
+
+        public override long Position
+        {
+            get
+            {
+                long result = _stream.Length;
+                _session.Logger.WriteLineLevel(2, "File position = {0}", result);
+                return result;
+            }
+
+            set
+            {
+                _session.Logger.WriteLineLevel(2, "Setting file position to {0}", value);
+                _stream.Position = value;
+            }
+        }
+
+        private FileStream _stream;
         private Session _session;
         private Session _session;
     }
     }
 }
 }