Преглед на файлове

Bug fix: Potential failure when waiting for a command executed from Console window is aborted

Originally, I resolved this using new TMulticastEvent, but once I've realized that TUnixDirView::DoChangeDirectory implementation is noop, it was not needed anymore.
Keeping the multicast implementation, as it may be useful in future.

(cherry picked from commit d3cb36914199408a6761305f668fbc6c2c8c4d84)

Source commit: fed58420d4b99eb18062aaf1b40020325227cd0f
Martin Prikryl преди 4 години
родител
ревизия
0692da8c23
променени са 4 файла, в които са добавени 81 реда и са изтрити 15 реда
  1. 0 14
      source/components/UnixDirView.cpp
  2. 0 1
      source/components/UnixDirView.h
  3. 77 0
      source/core/Common.h
  4. 4 0
      source/forms/Console.cpp

+ 0 - 14
source/components/UnixDirView.cpp

@@ -523,11 +523,6 @@ void __fastcall TUnixDirView::DoSetTerminal(TTerminal * value, bool Replace)
       {
         FTerminal->OnStartReadDirectory = NULL;
       }
-      DebugAssert((FTerminal->OnChangeDirectory == DoChangeDirectory) || Replace);
-      if (FTerminal->OnChangeDirectory == DoChangeDirectory)
-      {
-        FTerminal->OnChangeDirectory = NULL;
-      }
       if (!value || !value->Files->Loaded)
       {
         ClearItems();
@@ -543,11 +538,9 @@ void __fastcall TUnixDirView::DoSetTerminal(TTerminal * value, bool Replace)
     {
       FTerminal->OnReadDirectory = DoReadDirectory;
       FTerminal->OnStartReadDirectory = DoStartReadDirectory;
-      FTerminal->OnChangeDirectory = DoChangeDirectory;
       FTerminal->Files->IncludeParentDirectory = AddParentDir;
       if (FTerminal->Files->Loaded)
       {
-        DoChangeDirectory(FTerminal);
         DoStartReadDirectory(FTerminal); // just for style and the assertions
         DoReadDirectoryImpl(FTerminal, false);
       }
@@ -622,13 +615,6 @@ void __fastcall TUnixDirView::DoReadDirectoryImpl(TObject * /*Sender*/, bool Rel
 #endif
 }
 //---------------------------------------------------------------------------
-void __fastcall TUnixDirView::DoChangeDirectory(TObject * /*Sender*/)
-{
-#ifndef DESIGN_ONLY
-//  Reload(false);
-#endif
-}
-//---------------------------------------------------------------------------
 bool __fastcall TUnixDirView::GetDirOK()
 {
 #ifndef DESIGN_ONLY

+ 0 - 1
source/components/UnixDirView.h

@@ -44,7 +44,6 @@ protected:
   virtual void __fastcall DDMenuDone(TObject* Sender, HMENU AMenu);
   virtual void __fastcall DDChooseEffect(int grfKeyState, int &dwEffect, int PreferredEffect);
   virtual void __fastcall AddToDragFileList(TFileList* FileList, TListItem* Item);
-  void __fastcall DoChangeDirectory(TObject * Sender);
   void __fastcall DoReadDirectory(TObject * Sender, bool ReloadOnly);
   void __fastcall DoReadDirectoryImpl(TObject * Sender, bool ReloadOnly);
   void __fastcall DoStartReadDirectory(TObject * Sender);

+ 77 - 0
source/core/Common.h

@@ -441,6 +441,83 @@ private:
   TSecondToFirst FSecondToFirst;
 };
 //---------------------------------------------------------------------------
+template<class T>
+class TMulticastEvent
+{
+public:
+  TMulticastEvent()
+  {
+    // noop
+  }
+
+  TMulticastEvent(const TMulticastEvent & Other) :
+    FEventHandlers(Other.FEventHandlers)
+  {
+  }
+
+  explicit TMulticastEvent(T EventHandler)
+  {
+    Add(EventHandler);
+  }
+
+  void Add(T EventHandler)
+  {
+    DebugAssert(EventHandler != NULL);
+    DebugAssert(Find(EventHandler) == FEventHandlers.end());
+    FEventHandlers.push_back(EventHandler);
+  }
+
+  void Remove(T EventHandler)
+  {
+    TEventHandlers::iterator I = Find(EventHandler);
+    if (DebugAlwaysTrue(I != FEventHandlers.end()))
+    {
+      FEventHandlers.erase(I);
+    }
+  }
+
+  template<typename P>
+  void Invoke(const P & p)
+  {
+    TEventHandlers::iterator I = FEventHandlers.begin();
+    while (I != FEventHandlers.end())
+    {
+      (*I)(p);
+      ++I;
+    }
+  }
+
+  bool Contains(T EventHandler)
+  {
+    return (Find(EventHandler) != FEventHandlers.end());
+  }
+
+  bool Any() const
+  {
+    return (FEventHandlers.size() > 0);
+  }
+
+  bool operator==(const TMulticastEvent<T> Other) const
+  {
+    return (FEventHandlers == Other.FEventHandlers);
+  }
+
+  void operator=(const TMulticastEvent<T> & Other)
+  {
+    FEventHandlers = Other.FEventHandlers;
+  }
+
+private:
+  typedef std::vector<T> TEventHandlers;
+  TEventHandlers FEventHandlers;
+
+  TEventHandlers::iterator Find(T EventHandler)
+  {
+    return std::find(FEventHandlers.begin(), FEventHandlers.end(), EventHandler);
+  }
+
+};
+//---------------------------------------------------------------------------
 typedef std::vector<UnicodeString> TUnicodeStringVector;
 //---------------------------------------------------------------------------
 #endif

+ 4 - 0
source/forms/Console.cpp

@@ -93,6 +93,10 @@ void __fastcall TConsoleDialog::SetTerminal(TTerminal * value)
     if (FTerminal)
     {
       OutputMemo->Clear();
+      // If ever these events are used elsewhere, use TMulticastEvent,
+      // to avoid problems when the connnection is lost while the dialog is opened.
+      DebugAssert(FTerminal->OnChangeDirectory == NULL);
+      DebugAssert(FTerminal->OnClose == NULL);
       FOldChangeDirectory = FTerminal->OnChangeDirectory;
       FTerminal->OnChangeDirectory = DoChangeDirectory;
       // avoid reloading directory after each change of current directory from console