Sfoglia il codice sorgente

Reporting errors when XML logging fails as disk runs out of space

Source commit: 5434d35f3a0441633b2c55fd06fd753aacf14c85
Martin Prikryl 9 anni fa
parent
commit
4e9fe0e04f

+ 21 - 10
dotnet/Session.cs

@@ -218,19 +218,13 @@ namespace WinSCP
                         {
                             if (_error.Count > 0)
                             {
-                                string[] error = new string[_error.Count];
-                                _error.CopyTo(error, 0);
-                                logExplanation =
-                                    string.Format(
-                                        CultureInfo.CurrentCulture, "Error output was \"{0}\". ", string.Join(Environment.NewLine, error));
+                                logExplanation = GetErrorOutputMessage();
                             }
                             else if (Output.Count > 0)
                             {
-                                string[] output = new string[Output.Count];
-                                Output.CopyTo(output, 0);
                                 logExplanation =
                                     string.Format(
-                                        CultureInfo.CurrentCulture, "Output was \"{0}\". ", string.Join(Environment.NewLine, output));
+                                        CultureInfo.CurrentCulture, "Output was \"{0}\". ", ListToString(Output));
                             }
                             else
                             {
@@ -296,7 +290,7 @@ namespace WinSCP
                     }
 
                 }
-                catch(Exception e)
+                catch (Exception e)
                 {
                     Logger.WriteLine("Exception: {0}", e);
                     Cleanup();
@@ -305,6 +299,24 @@ namespace WinSCP
             }
         }
 
+        internal string GetErrorOutputMessage()
+        {
+            string result = null;
+            if (_error.Count > 0)
+            {
+                result = string.Format(CultureInfo.CurrentCulture, "Error output was \"{0}\". ", ListToString(_error));
+            }
+            return result;
+        }
+
+        private static string ListToString(StringCollection list)
+        {
+            string[] error = new string[list.Count];
+            list.CopyTo(error, 0);
+            string s = string.Join(Environment.NewLine, error);
+            return s;
+        }
+
         public string ScanFingerprint(SessionOptions sessionOptions)
         {
             using (Logger.CreateCallstackAndLock())
@@ -341,7 +353,6 @@ namespace WinSCP
                         CheckForTimeout();
                     }
 
-
                     string output = string.Join(Environment.NewLine, new List<string>(Output).ToArray());
                     if (_process.ExitCode == 0)
                     {

+ 1 - 0
dotnet/internal/ExeSessionProcess.cs

@@ -267,6 +267,7 @@ namespace WinSCP
                 while (!AbortedOrExited())
                 {
                     _logger.WriteLineLevel(1, "Waiting for request event");
+                    // Keep in sync with a delay in SessionLogReader.DoRead
                     if (_requestEvent.WaitOne(100, false))
                     {
                         _logger.WriteLineLevel(1, "Got request event");

+ 11 - 1
dotnet/internal/SessionLogReader.cs

@@ -3,6 +3,7 @@ using System.Diagnostics;
 using System.IO;
 using System.Xml;
 using System.Text;
+using System.Threading;
 
 namespace WinSCP
 {
@@ -138,7 +139,16 @@ namespace WinSCP
                         // check if the the root cause was session abort
                         Session.CheckForTimeout();
                         LogContents();
-                        throw new SessionLocalException(Session, "Error parsing session log file", e);
+                        string message = "Error parsing session log file";
+                        // This is possibly a race condition, as we may not have processed the event with the error yet
+                        // The ExeSessionProcess loops every 100ms
+                        Thread.Sleep(200);
+                        string s = Session.GetErrorOutputMessage();
+                        if (!string.IsNullOrEmpty(s))
+                        {
+                            message += " - " + s;
+                        }
+                        throw new SessionLocalException(Session, message, e);
                     }
                 }
 

+ 32 - 14
source/core/SessionInfo.cpp

@@ -1339,6 +1339,7 @@ void __fastcall TActionLog::Init(TSessionUI * UI, TSessionData * SessionData,
   FCurrentFileName = L"";
   FLogging = false;
   FClosed = false;
+  FFailed = false;
   FPendingActions = new TList();
   FIndent = L"  ";
   FInGroup = false;
@@ -1371,30 +1372,47 @@ void __fastcall TActionLog::Add(const UnicodeString & Line)
       try
       {
         UTF8String UtfLine = UTF8String(Line);
-        fwrite(UtfLine.c_str(), 1, UtfLine.Length(), (FILE *)FFile);
-        fwrite("\n", 1, 1, (FILE *)FFile);
+        size_t Written =
+          fwrite(UtfLine.c_str(), 1, UtfLine.Length(), (FILE *)FFile);
+        if (Written != static_cast<size_t>(UtfLine.Length()))
+        {
+          throw ECRTExtException(L"");
+        }
+        #ifdef _DEBUG
+        #endif
+        Written =
+          fwrite("\n", 1, 1, (FILE *)FFile);
+        if (Written != 1)
+        {
+          throw ECRTExtException(L"");
+        }
       }
       catch (Exception &E)
       {
         FCriticalSection->Release();
 
-        // We failed logging, turn it off and notify user.
-        FConfiguration->LogActions = false;
-        if (FConfiguration->LogActionsRequired)
-        {
-          throw EFatal(&E, LoadStr(LOG_FATAL_ERROR));
-        }
-        else
+        // avoid endless loop when trying to close tags when closing log, when logging has failed
+        if (!FFailed)
         {
-          try
+          FFailed = true;
+          // We failed logging, turn it off and notify user.
+          FConfiguration->LogActions = false;
+          if (FConfiguration->LogActionsRequired)
           {
-            throw ExtException(&E, LoadStr(LOG_GEN_ERROR));
+            throw EFatal(&E, LoadStr(LOG_FATAL_ERROR));
           }
-          catch (Exception &E)
+          else
           {
-            if (FUI != NULL)
+            try
+            {
+              throw ExtException(&E, LoadStr(LOG_GEN_ERROR));
+            }
+            catch (Exception &E)
             {
-              FUI->HandleExtendedException(&E);
+              if (FUI != NULL)
+              {
+                FUI->HandleExtendedException(&E);
+              }
             }
           }
         }

+ 1 - 0
source/core/SessionInfo.h

@@ -331,6 +331,7 @@ private:
   TSessionUI * FUI;
   TSessionData * FSessionData;
   TList * FPendingActions;
+  bool FFailed;
   bool FClosed;
   bool FInGroup;
   UnicodeString FIndent;