[nemiver] Don't loop forever on cycles (Closes: #584464)



commit 519c0f829a52346443f6d59882c5d63fb4e253a7
Author: Dodji Seketeli <dodji redhat com>
Date:   Tue Jun 2 22:11:01 2009 +0200

    Don't loop forever on cycles (Closes: #584464)
    
    	* src/dbgengine/nmv-i-var-walker.h:
    	(IVarWalker::set_maximum_member_depth,
    	 IVarWalker::get_maximum_member_depth): New abstract
    	ifaces.
    	* src/dbgengine/nmv-var-walker.cc (VarWalker::set_maximum_member_depth,
    	VarWalker::get_maximum_member_depth): New concrete implementations.
    	* src/dbgengine/nmv-varobj-walker.cc (VarobjWalker::set_maximum_member_depth,
    	VarobjWalker::get_maximum_member_depth): Likewise.
    	(VarobjWalker::on_variable_unfolded_signal: Add a max depth guard to avoid
    	looping forever on some huge datastructures.
    	(VarobjWalker::do_walk_variable_real): Likewise. Don't
    	dereference pointers, otherwise we might cycle forever on
    	datastructures that have cycles. Make sure to pass the right
    	variable to the visited_variable_signal.
---
 src/dbgengine/nmv-i-var-walker.h     |    7 +++-
 src/dbgengine/nmv-var-walker.cc      |   15 ++++++++
 src/dbgengine/nmv-varobj-walker.cc   |   65 ++++++++++++++++++++++++++-------
 src/persp/dbgperspective/Makefile.am |    3 +-
 4 files changed, 74 insertions(+), 16 deletions(-)

diff --git a/src/dbgengine/nmv-i-var-walker.h b/src/dbgengine/nmv-i-var-walker.h
index ade767e..8575659 100644
--- a/src/dbgengine/nmv-i-var-walker.h
+++ b/src/dbgengine/nmv-i-var-walker.h
@@ -87,7 +87,12 @@ public:
 
     /// gets the debugger the walker is connected to
     virtual IDebuggerSafePtr get_debugger () const = 0;
-};//end IVarWalker
+
+    /// accessor of the maximum depth of variable members to explore.
+    /// this can prevent inifite recursions.
+    virtual void set_maximum_member_depth (unsigned a_max_depth) = 0;
+    virtual unsigned get_maximum_member_depth () const = 0;
+}; // end IVarWalker
 
 NEMIVER_END_NAMESPACE (nemiver)
 
diff --git a/src/dbgengine/nmv-var-walker.cc b/src/dbgengine/nmv-var-walker.cc
index ba61343..bbd1bad 100644
--- a/src/dbgengine/nmv-var-walker.cc
+++ b/src/dbgengine/nmv-var-walker.cc
@@ -114,6 +114,10 @@ public:
     const IDebugger::VariableSafePtr get_variable () const;
 
     IDebuggerSafePtr get_debugger () const ;
+
+    void set_maximum_member_depth (unsigned a_max_depth);
+
+    unsigned get_maximum_member_depth () const;
 };//end class VarWalker
 
 void
@@ -318,6 +322,17 @@ VarWalker::get_debugger () const
     return m_debugger.do_dynamic_cast<IDebugger> ();
 }
 
+void
+VarWalker::set_maximum_member_depth (unsigned)
+{
+}
+
+unsigned
+VarWalker::get_maximum_member_depth () const
+{
+    return 0;
+}
+
 //the dynmod used to instanciate the VarWalker service object
 //and return an interface on it.
 struct VarWalkerDynMod : public  DynamicModule {
diff --git a/src/dbgengine/nmv-varobj-walker.cc b/src/dbgengine/nmv-varobj-walker.cc
index fef2953..462b3b5 100644
--- a/src/dbgengine/nmv-varobj-walker.cc
+++ b/src/dbgengine/nmv-varobj-walker.cc
@@ -27,6 +27,7 @@
 #include "nmv-i-var-walker.h"
 #include "nmv-gdb-engine.h"
 #include "common/nmv-sequence.h"
+#include "nmv-i-lang-trait.h"
 
 using std::list;
 using std::map;
@@ -41,8 +42,7 @@ typedef SafePtr<nemiver::GDBEngine, ObjectRef, ObjectUnref> GDBEngineSafePtr;
 
 NEMIVER_BEGIN_NAMESPACE (nemiver)
 
-const UString VAR_WALKER_COOKIE="var-walker-cookie";
-
+static const unsigned MAX_DEPTH = 256;
 
 class VarobjWalker : public IVarWalker, public sigc::trackable
 {
@@ -59,13 +59,17 @@ class VarobjWalker : public IVarWalker, public sigc::trackable
     // The count of on going variable unfolding
     int m_variable_unfolds;
 
+    unsigned m_max_depth;
+
     VarobjWalker (); // Don't call this constructor.
 
 public:
+
     VarobjWalker (DynamicModule *a_dynmod) :
         IVarWalker (a_dynmod),
         m_do_walk (false),
-        m_variable_unfolds (0)
+        m_variable_unfolds (0),
+        m_max_depth (MAX_DEPTH)
     {
     }
 
@@ -93,11 +97,17 @@ public:
 
     IDebuggerSafePtr get_debugger () const;
 
+    void set_maximum_member_depth (unsigned a_max_depth);
+
+    unsigned get_maximum_member_depth () const;
+
     void delete_varobj_if_necessary ();
 
-    void do_walk_variable_real (const IDebugger::VariableSafePtr);
+    void do_walk_variable_real (const IDebugger::VariableSafePtr,
+                                unsigned a_max_depth);
 
-    void on_variable_unfolded_signal (const IDebugger::VariableSafePtr a_var);
+    void on_variable_unfolded_signal (const IDebugger::VariableSafePtr a_var,
+                                      unsigned max_depth);
 
     void on_variable_created_signal (const IDebugger::VariableSafePtr a_var);
 }; // end class VarobjWalker.
@@ -166,7 +176,7 @@ VarobjWalker::do_walk_variable (const UString &)
             THROW ("expecting a non null m_variable!");
         }
     }
-    do_walk_variable_real (m_variable);
+    do_walk_variable_real (m_variable, m_max_depth);
 
 }
 
@@ -187,6 +197,22 @@ VarobjWalker::get_debugger () const
 }
 
 void
+VarobjWalker::set_maximum_member_depth (unsigned a_max_depth)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    m_max_depth = a_max_depth;
+}
+
+unsigned
+VarobjWalker::get_maximum_member_depth () const
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    return m_max_depth;
+}
+
+void
 VarobjWalker::delete_varobj_if_necessary ()
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
@@ -201,18 +227,28 @@ VarobjWalker::delete_varobj_if_necessary ()
 }
 
 void
-VarobjWalker::do_walk_variable_real (const IDebugger::VariableSafePtr a_var)
+VarobjWalker::do_walk_variable_real (const IDebugger::VariableSafePtr a_var,
+                                     unsigned a_max_depth)
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
 
     THROW_IF_FAIL (a_var);
 
-    if (a_var->needs_unfolding ()) {
+    LOG_DD ("internal var name: " << a_var->internal_name ()
+            << "depth: " << (int) a_max_depth);
+
+    if (a_max_depth == 0)
+        return;
+
+    if (a_var->needs_unfolding ()
+        && m_debugger->get_language_trait ().is_variable_compound (a_var)) {
         LOG_DD ("needs unfolding");
         m_variable_unfolds++;
         m_debugger->unfold_variable
-            (a_var, sigc::mem_fun (*this,
-                                   &VarobjWalker::on_variable_unfolded_signal));
+            (a_var,
+             sigc::bind (sigc::mem_fun (*this,
+                                   &VarobjWalker::on_variable_unfolded_signal),
+                         a_max_depth - 1));
     } else if (!a_var->members ().empty ()) {
         LOG_DD ("children need visiting");
         visited_variable_node_signal ().emit (a_var);
@@ -220,20 +256,21 @@ VarobjWalker::do_walk_variable_real (const IDebugger::VariableSafePtr a_var)
         for (it = a_var->members ().begin ();
              it != a_var->members ().end ();
              ++ it) {
-            do_walk_variable_real (*it);
+            do_walk_variable_real (*it, a_max_depth - 1);
         }
     } else {
         LOG_DD ("else finished ?. m_variable_unfolds: "
                 << (int) m_variable_unfolds);
         visited_variable_node_signal ().emit (a_var);
         if (m_variable_unfolds == 0)
-            visited_variable_signal ().emit (a_var);
+            visited_variable_signal ().emit (m_variable);
     }
 
 }
 
 void
-VarobjWalker::on_variable_unfolded_signal (const IDebugger::VariableSafePtr a_var)
+VarobjWalker::on_variable_unfolded_signal (const IDebugger::VariableSafePtr a_var,
+                                           unsigned a_max_depth)
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
 
@@ -241,7 +278,7 @@ VarobjWalker::on_variable_unfolded_signal (const IDebugger::VariableSafePtr a_va
 
     m_variable_unfolds--;
     visited_variable_node_signal ().emit (a_var);
-    do_walk_variable_real (a_var);
+    do_walk_variable_real (a_var, a_max_depth);
     if (m_variable_unfolds == 0) {
         THROW_IF_FAIL (m_variable);
         visited_variable_signal ().emit (m_variable);
diff --git a/src/persp/dbgperspective/Makefile.am b/src/persp/dbgperspective/Makefile.am
index 74d08d5..a81d704 100644
--- a/src/persp/dbgperspective/Makefile.am
+++ b/src/persp/dbgperspective/Makefile.am
@@ -97,7 +97,8 @@ libdbgperspectiveplugin_la_LDFLAGS= -module -avoid-version -Wl,--as-needed
 libdbgperspectiveplugin_la_LIBADD= \
 @NEMIVERDBGPERSP_LIBS@ \
 $(top_builddir)/src/common/libnemivercommon.la \
-$(top_builddir)/src/uicommon/libnemiveruicommon.la
+$(top_builddir)/src/uicommon/libnemiveruicommon.la \
+$(top_builddir)/src/dbgengine/libdebuggerutils.la
 
 INCLUDES= NEMIVERDBGPERSP_CFLAGS@ -DENABLE_NLS=1 -DDATADIR=\"${datadir}\" \
 -I$(top_srcdir)/src \



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]