mib updated this revision to Diff 515498.
mib added a comment.

Fix issue when returning a non-initialized passthrough listener from the SBAPI


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D148397/new/

https://reviews.llvm.org/D148397

Files:
  lldb/include/lldb/API/SBAttachInfo.h
  lldb/include/lldb/API/SBLaunchInfo.h
  lldb/include/lldb/Target/Process.h
  lldb/include/lldb/Utility/Broadcaster.h
  lldb/include/lldb/Utility/Listener.h
  lldb/include/lldb/Utility/ProcessInfo.h
  lldb/source/API/SBAttachInfo.cpp
  lldb/source/API/SBLaunchInfo.cpp
  lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
  lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
  lldb/source/Target/Target.cpp
  lldb/source/Utility/Broadcaster.cpp
  lldb/source/Utility/Listener.cpp

Index: lldb/source/Utility/Listener.cpp
===================================================================
--- lldb/source/Utility/Listener.cpp
+++ lldb/source/Utility/Listener.cpp
@@ -35,7 +35,7 @@
 
 Listener::Listener(const char *name)
     : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(),
-      m_events_mutex() {
+      m_events_mutex(), m_is_passthrough() {
   Log *log = GetLog(LLDBLog::Object);
   if (log != nullptr)
     LLDB_LOGF(log, "%p Listener::Listener('%s')", static_cast<void *>(this),
@@ -302,7 +302,8 @@
       // to return it so it should be okay to get the next event off the queue
       // here - and it might be useful to do that in the "DoOnRemoval".
       lock.unlock();
-      event_sp->DoOnRemoval();
+      if (!m_is_passthrough)
+        event_sp->DoOnRemoval();
     }
     return true;
   }
Index: lldb/source/Utility/Broadcaster.cpp
===================================================================
--- lldb/source/Utility/Broadcaster.cpp
+++ lldb/source/Utility/Broadcaster.cpp
@@ -228,6 +228,8 @@
                       &m_broadcaster, event_type))
       return;
     hijacking_listener_sp->AddEvent(event_sp);
+    if (m_passthrough_listener)
+      m_passthrough_listener->AddEvent(event_sp);
   } else {
     for (auto &pair : GetListeners()) {
       if (!(pair.second & event_type))
@@ -237,6 +239,8 @@
         continue;
 
       pair.first->AddEvent(event_sp);
+      if (m_passthrough_listener)
+        m_passthrough_listener->AddEvent(event_sp);
     }
   }
 }
Index: lldb/source/Target/Target.cpp
===================================================================
--- lldb/source/Target/Target.cpp
+++ lldb/source/Target/Target.cpp
@@ -3193,6 +3193,8 @@
     // Since we didn't have a platform launch the process, launch it here.
     if (m_process_sp) {
       m_process_sp->HijackProcessEvents(launch_info.GetHijackListener());
+      m_process_sp->SetPassthroughListener(
+          launch_info.GetPassthroughListener());
       error = m_process_sp->Launch(launch_info);
     }
   }
Index: lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
===================================================================
--- lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -423,6 +423,8 @@
 
         if (process_sp) {
           process_sp->HijackProcessEvents(launch_info.GetHijackListener());
+          process_sp->SetPassthroughListener(
+              launch_info.GetPassthroughListener());
 
           error = process_sp->ConnectRemote(connect_url.c_str());
           // Retry the connect remote one time...
@@ -515,6 +517,8 @@
               ListenerSP listener_sp = attach_info.GetHijackListener();
               if (listener_sp)
                 process_sp->HijackProcessEvents(listener_sp);
+              process_sp->SetPassthroughListener(
+                  attach_info.GetPassthroughListener());
               error = process_sp->Attach(attach_info);
             }
 
Index: lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
===================================================================
--- lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -401,6 +401,8 @@
           attach_info.SetHijackListener(listener_sp);
         }
         process_sp->HijackProcessEvents(listener_sp);
+        process_sp->SetPassthroughListener(
+            attach_info.GetPassthroughListener());
         error = process_sp->Attach(attach_info);
       }
     }
@@ -458,6 +460,7 @@
   LLDB_LOG(log, "successfully created process");
 
   process_sp->HijackProcessEvents(launch_info.GetHijackListener());
+  process_sp->SetPassthroughListener(launch_info.GetPassthroughListener());
 
   // Log file actions.
   if (log) {
Index: lldb/source/API/SBLaunchInfo.cpp
===================================================================
--- lldb/source/API/SBLaunchInfo.cpp
+++ lldb/source/API/SBLaunchInfo.cpp
@@ -17,6 +17,7 @@
 #include "lldb/API/SBStructuredData.h"
 #include "lldb/Core/StructuredDataImpl.h"
 #include "lldb/Host/ProcessLaunchInfo.h"
+#include "lldb/Utility/Listener.h"
 #include "lldb/Utility/ScriptedMetadata.h"
 
 using namespace lldb;
@@ -387,3 +388,24 @@
   metadata_sp = std::make_shared<ScriptedMetadata>(class_name, dict_sp);
   m_opaque_sp->SetScriptedMetadata(metadata_sp);
 }
+
+SBListener SBLaunchInfo::GetPassthroughListener() {
+  LLDB_INSTRUMENT_VA(this);
+
+  lldb::ListenerSP passthrough_sp = m_opaque_sp->GetPassthroughListener();
+  if (!passthrough_sp)
+    return SBListener();
+  return SBListener(passthrough_sp);
+}
+
+void SBLaunchInfo::SetPassthroughListener(SBListener &listener) {
+  LLDB_INSTRUMENT_VA(this, listener);
+
+  ListenerSP listener_sp = listener.GetSP();
+  if (listener_sp && listener.IsValid())
+    listener_sp->SetPassthrough(true);
+  else
+    listener_sp = nullptr;
+
+  m_opaque_sp->SetPassthroughListener(listener_sp);
+}
Index: lldb/source/API/SBAttachInfo.cpp
===================================================================
--- lldb/source/API/SBAttachInfo.cpp
+++ lldb/source/API/SBAttachInfo.cpp
@@ -254,6 +254,27 @@
   m_opaque_sp->SetListener(listener.GetSP());
 }
 
+SBListener SBAttachInfo::GetPassthroughListener() {
+  LLDB_INSTRUMENT_VA(this);
+
+  lldb::ListenerSP passthrough_sp = m_opaque_sp->GetPassthroughListener();
+  if (!passthrough_sp)
+    return SBListener();
+  return SBListener(passthrough_sp);
+}
+
+void SBAttachInfo::SetPassthroughListener(SBListener &listener) {
+  LLDB_INSTRUMENT_VA(this, listener);
+
+  ListenerSP listener_sp = listener.GetSP();
+  if (listener_sp && listener.IsValid())
+    listener_sp->SetPassthrough(true);
+  else
+    listener_sp = nullptr;
+
+  m_opaque_sp->SetPassthroughListener(listener_sp);
+}
+
 const char *SBAttachInfo::GetScriptedProcessClassName() const {
   LLDB_INSTRUMENT_VA(this);
 
Index: lldb/include/lldb/Utility/ProcessInfo.h
===================================================================
--- lldb/include/lldb/Utility/ProcessInfo.h
+++ lldb/include/lldb/Utility/ProcessInfo.h
@@ -110,6 +110,14 @@
     m_hijack_listener_sp = listener_sp;
   }
 
+  lldb::ListenerSP GetPassthroughListener() const {
+    return m_passthrough_listener_sp;
+  }
+
+  void SetPassthroughListener(const lldb::ListenerSP &listener_sp) {
+    m_passthrough_listener_sp = listener_sp;
+  }
+
 protected:
   FileSpec m_executable;
   std::string m_arg0; // argv[0] if supported. If empty, then use m_executable.
@@ -124,6 +132,7 @@
   lldb::ScriptedMetadataSP m_scripted_metadata_sp = nullptr;
   lldb::ListenerSP m_listener_sp = nullptr;
   lldb::ListenerSP m_hijack_listener_sp = nullptr;
+  lldb::ListenerSP m_passthrough_listener_sp = nullptr;
 };
 
 // ProcessInstanceInfo
Index: lldb/include/lldb/Utility/Listener.h
===================================================================
--- lldb/include/lldb/Utility/Listener.h
+++ lldb/include/lldb/Utility/Listener.h
@@ -95,6 +95,10 @@
 
   size_t HandleBroadcastEvent(lldb::EventSP &event_sp);
 
+  void SetPassthrough(bool is_passthrough) {
+    m_is_passthrough = is_passthrough;
+  }
+
 private:
   // Classes that inherit from Listener can see and modify these
   struct BroadcasterInfo {
@@ -134,6 +138,7 @@
   std::mutex m_events_mutex; // Protects m_broadcasters and m_events
   std::condition_variable m_events_condition;
   broadcaster_manager_collection m_broadcaster_managers;
+  bool m_is_passthrough = false;
 
   void BroadcasterWillDestruct(Broadcaster *);
 
Index: lldb/include/lldb/Utility/Broadcaster.h
===================================================================
--- lldb/include/lldb/Utility/Broadcaster.h
+++ lldb/include/lldb/Utility/Broadcaster.h
@@ -406,6 +406,10 @@
 
   lldb::BroadcasterManagerSP GetManager();
 
+  virtual void SetPassthroughListener(lldb::ListenerSP listener_sp) {
+    m_broadcaster_sp->m_passthrough_listener = listener_sp;
+  }
+
 protected:
   /// BroadcasterImpl contains the actual Broadcaster implementation.  The
   /// Broadcaster makes a BroadcasterImpl which lives as long as it does.  The
@@ -513,6 +517,10 @@
     /// for now this is just for private hijacking.
     std::vector<uint32_t> m_hijacking_masks;
 
+    /// A optional listener that all private events get also broadcasted to,
+    /// on top the hijacked / default listeners.
+    lldb::ListenerSP m_passthrough_listener = nullptr;
+
   private:
     BroadcasterImpl(const BroadcasterImpl &) = delete;
     const BroadcasterImpl &operator=(const BroadcasterImpl &) = delete;
Index: lldb/include/lldb/Target/Process.h
===================================================================
--- lldb/include/lldb/Target/Process.h
+++ lldb/include/lldb/Target/Process.h
@@ -380,6 +380,10 @@
     return GetStaticBroadcasterClass();
   }
 
+  void SetPassthroughListener(lldb::ListenerSP listener_sp) override {
+    Broadcaster::SetPassthroughListener(listener_sp);
+  }
+
 /// A notification structure that can be used by clients to listen
 /// for changes in a process's lifetime.
 ///
Index: lldb/include/lldb/API/SBLaunchInfo.h
===================================================================
--- lldb/include/lldb/API/SBLaunchInfo.h
+++ lldb/include/lldb/API/SBLaunchInfo.h
@@ -92,6 +92,25 @@
   /// allows a different listener to be used to listen for process events.
   void SetListener(SBListener &listener);
 
+  /// Get the passthrough listener that receive public process events,
+  /// additionally to the default process event listener.
+  ///
+  /// If no listener has been set via a call to
+  /// SBLaunchInfo::SetPassthroughListener(), then an invalid SBListener will
+  /// be returned (SBListener::IsValid() will return false). If a listener
+  /// has been set, then the valid listener object will be returned.
+  SBListener GetPassthroughListener();
+
+  /// Set the passthrough listener that will receive public process events,
+  /// additionally to the default process event listener.
+  ///
+  /// By default a process have no passthrough event listener.
+  /// Calling this function allows public process events to be broadcasted to an
+  /// additional listener on top of the default process event listener.
+  /// If the `listener` argument is invalid (SBListener::IsValid() will
+  /// return false), this will clear the passthrough listener.
+  void SetPassthroughListener(SBListener &listener);
+
   uint32_t GetNumArguments();
 
   const char *GetArgumentAtIndex(uint32_t idx);
Index: lldb/include/lldb/API/SBAttachInfo.h
===================================================================
--- lldb/include/lldb/API/SBAttachInfo.h
+++ lldb/include/lldb/API/SBAttachInfo.h
@@ -168,6 +168,25 @@
   /// allows a different listener to be used to listen for process events.
   void SetListener(SBListener &listener);
 
+  /// Get the passthrough listener that receive public process events,
+  /// additionally to the default process event listener.
+  ///
+  /// If no listener has been set via a call to
+  /// SBLaunchInfo::SetPassthroughListener(), then an invalid SBListener will
+  /// be returned (SBListener::IsValid() will return false). If a listener
+  /// has been set, then the valid listener object will be returned.
+  SBListener GetPassthroughListener();
+
+  /// Set the passthrough listener that will receive public process events,
+  /// additionally to the default process event listener.
+  ///
+  /// By default a process have no passthrough event listener.
+  /// Calling this function allows public process events to be broadcasted to an
+  /// additional listener on top of the default process event listener.
+  /// If the `listener` argument is invalid (SBListener::IsValid() will
+  /// return false), this will clear the passthrough listener.
+  void SetPassthroughListener(SBListener &listener);
+
   const char *GetScriptedProcessClassName() const;
 
   void SetScriptedProcessClassName(const char *class_name);
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to