[Bug 1862] NS_LOG="Time=*|prefix_time" causes stack overflow
authorPeter D. Barnes, Jr. <barnes26@llnl.gov>
Fri, 21 Feb 2014 16:27:43 -0800
changeset 10626 16bbfc4cb29d
parent 10625 c3e9a5530654
child 10627 7423d0b3ce9a
[Bug 1862] NS_LOG="Time=*|prefix_time" causes stack overflow
RELEASE_NOTES
src/core/model/attribute-accessor-helper.h
src/core/model/log.cc
src/core/model/log.h
src/core/model/time.cc
src/core/model/unix-system-mutex.cc
--- a/RELEASE_NOTES	Fri Feb 21 16:25:43 2014 -0800
+++ b/RELEASE_NOTES	Fri Feb 21 16:27:43 2014 -0800
@@ -46,6 +46,7 @@
 - Bug 1852 - cairo-wideint-private.h error cannot find definitions for fixed-width integral types
 - Bug 1853 - NS_LOG_FUNCTION broken on OSX 10.9
 - Bug 1855 - SixLowPanNetDevice is not correctly indexed
+- Bug 1862 - NS_LOG="Time=*|prefix_time" causes stack overflow
 
 Release 3.19
 =============
--- a/src/core/model/attribute-accessor-helper.h	Fri Feb 21 16:25:43 2014 -0800
+++ b/src/core/model/attribute-accessor-helper.h	Fri Feb 21 16:27:43 2014 -0800
@@ -28,6 +28,7 @@
  * \ingroup AttributeHelper
  */
 template <typename V, typename T1>
+inline
 Ptr<const AttributeAccessor>
 MakeAccessorHelper (T1 a1);
 
@@ -35,6 +36,7 @@
  * \ingroup AttributeHelper
  */
 template <typename V, typename T1, typename T2>
+inline
 Ptr<const AttributeAccessor>
 MakeAccessorHelper (T1 a1, T2 a2);
 
@@ -94,6 +96,7 @@
 };
 
 template <typename V, typename T, typename U>
+inline
 Ptr<const AttributeAccessor>
 DoMakeAccessorHelperOne (U T::*memberVariable)
 {
@@ -132,6 +135,7 @@
 }
 
 template <typename V, typename T, typename U>
+inline
 Ptr<const AttributeAccessor>
 DoMakeAccessorHelperOne (U (T::*getter)(void) const)
 {
@@ -163,6 +167,7 @@
 
 
 template <typename V, typename T, typename U>
+inline
 Ptr<const AttributeAccessor>
 DoMakeAccessorHelperOne (void (T::*setter)(U))
 {
@@ -199,6 +204,7 @@
 }
 
 template <typename W, typename T, typename U, typename V>
+inline
 Ptr<const AttributeAccessor>
 DoMakeAccessorHelperTwo (void (T::*setter)(U),
                          V (T::*getter)(void) const)
@@ -240,6 +246,7 @@
 }
 
 template <typename W, typename T, typename U, typename V>
+inline
 Ptr<const AttributeAccessor>
 DoMakeAccessorHelperTwo (V (T::*getter)(void) const,
                          void (T::*setter)(U))
@@ -248,6 +255,7 @@
 }
 
 template <typename W, typename T, typename U, typename V>
+inline
 Ptr<const AttributeAccessor>
 DoMakeAccessorHelperTwo (bool (T::*setter)(U),
                          V (T::*getter)(void) const)
@@ -289,6 +297,7 @@
 }
 
 template <typename W, typename T, typename U, typename V>
+inline
 Ptr<const AttributeAccessor>
 DoMakeAccessorHelperTwo (bool (T::*getter)(void) const,
                          void (T::*setter)(U))
@@ -297,6 +306,7 @@
 }
 
 template <typename V, typename T1>
+inline
 Ptr<const AttributeAccessor>
 MakeAccessorHelper (T1 a1)
 {
@@ -304,6 +314,7 @@
 }
 
 template <typename V, typename T1, typename T2>
+inline
 Ptr<const AttributeAccessor>
 MakeAccessorHelper (T1 a1, T2 a2)
 {
--- a/src/core/model/log.cc	Fri Feb 21 16:25:43 2014 -0800
+++ b/src/core/model/log.cc	Fri Feb 21 16:27:43 2014 -0800
@@ -84,10 +84,11 @@
 }
 
 
-LogComponent::LogComponent (const std::string & name)
-  : m_levels (0), m_name (name)
+LogComponent::LogComponent (const std::string & name,
+                            const enum LogLevel mask /* = 0 */)
+  : m_levels (0), m_mask (mask), m_name (name)
 {
-  EnvVarCheck (name);
+  EnvVarCheck ();
 
   ComponentList *components = GetComponentList ();
   for (ComponentListI i = components->begin ();
@@ -103,7 +104,7 @@
 }
 
 void
-LogComponent::EnvVarCheck (const std::string & name)
+LogComponent::EnvVarCheck (void)
 {
 #ifdef HAVE_GETENV
   char *envVar = getenv ("NS_LOG");
@@ -112,7 +113,6 @@
       return;
     }
   std::string env = envVar;
-  std::string myName = name;
 
   std::string::size_type cur = 0;
   std::string::size_type next = 0;
@@ -125,7 +125,7 @@
       if (equal == std::string::npos)
         {
           component = tmp;
-          if (component == myName || component == "*" || component == "***")
+          if (component == m_name || component == "*" || component == "***")
             {
               int level = LOG_LEVEL_ALL | LOG_PREFIX_ALL;
               Enable ((enum LogLevel)level);
@@ -135,7 +135,7 @@
       else
         {
           component = tmp.substr (0, equal);
-          if (component == myName || component == "*")
+          if (component == m_name || component == "*")
             {
               int level = 0;
               std::string::size_type cur_lev;
@@ -242,7 +242,7 @@
 
 
 bool 
-LogComponent::IsEnabled (enum LogLevel level) const
+LogComponent::IsEnabled (const enum LogLevel level) const
 {
   //  LogComponentEnableEnvVar ();
   return (level & m_levels) ? 1 : 0;
@@ -255,13 +255,19 @@
 }
 
 void
-LogComponent::Enable (enum LogLevel level)
+LogComponent::SetMask (const enum LogLevel level)
 {
-  m_levels |= level;
+  m_mask |= level;
 }
 
 void 
-LogComponent::Disable (enum LogLevel level)
+LogComponent::Enable (const enum LogLevel level)
+{
+  m_levels |= (level & ~m_mask);
+}
+
+void 
+LogComponent::Disable (const enum LogLevel level)
 {
   m_levels &= ~level;
 }
@@ -272,8 +278,9 @@
   return m_name.c_str ();
 }
 
+/* static */
 std::string
-LogComponent::GetLevelLabel(const enum LogLevel level) const
+LogComponent::GetLevelLabel(const enum LogLevel level)
 {
   if (level == LOG_ERROR)
     {
--- a/src/core/model/log.h	Fri Feb 21 16:25:43 2014 -0800
+++ b/src/core/model/log.h	Fri Feb 21 16:27:43 2014 -0800
@@ -66,34 +66,34 @@
  *  Logging severity classes and levels.
  */
 enum LogLevel {
-  LOG_NONE           = 0x00000000, // no logging
+  LOG_NONE           = 0x00000000, //!< no logging
 
-  LOG_ERROR          = 0x00000001, // serious error messages only
+  LOG_ERROR          = 0x00000001, //!< serious error messages only
   LOG_LEVEL_ERROR    = 0x00000001,
 
-  LOG_WARN           = 0x00000002, // warning messages
+  LOG_WARN           = 0x00000002, //!< warning messages
   LOG_LEVEL_WARN     = 0x00000003,
 
-  LOG_DEBUG          = 0x00000004, // rare ad-hoc debug messages
+  LOG_DEBUG          = 0x00000004, //!< rare ad-hoc debug messages
   LOG_LEVEL_DEBUG    = 0x00000007,
 
-  LOG_INFO           = 0x00000008, // informational messages (e.g., banners)
+  LOG_INFO           = 0x00000008, //!< informational messages (e.g., banners)
   LOG_LEVEL_INFO     = 0x0000000f,
 
-  LOG_FUNCTION       = 0x00000010, // function tracing
+  LOG_FUNCTION       = 0x00000010, //!< function tracing
   LOG_LEVEL_FUNCTION = 0x0000001f, 
 
-  LOG_LOGIC          = 0x00000020, // control flow tracing within functions
+  LOG_LOGIC          = 0x00000020, //!< control flow tracing within functions
   LOG_LEVEL_LOGIC    = 0x0000003f,
 
-  LOG_ALL            = 0x0fffffff, // print everything
+  LOG_ALL            = 0x0fffffff, //!< print everything
   LOG_LEVEL_ALL      = LOG_ALL,
 
-  LOG_PREFIX_FUNC    = 0x80000000, // prefix all trace prints with function
-  LOG_PREFIX_TIME    = 0x40000000, // prefix all trace prints with simulation time
-  LOG_PREFIX_NODE    = 0x20000000, // prefix all trace prints with simulation node
-  LOG_PREFIX_LEVEL   = 0x10000000, // prefix all trace prints with log level (severity)
-  LOG_PREFIX_ALL     = 0xf0000000  // all prefixes
+  LOG_PREFIX_FUNC    = 0x80000000, //!< prefix all trace prints with function
+  LOG_PREFIX_TIME    = 0x40000000, //!< prefix all trace prints with simulation time
+  LOG_PREFIX_NODE    = 0x20000000, //!< prefix all trace prints with simulation node
+  LOG_PREFIX_LEVEL   = 0x10000000, //!< prefix all trace prints with log level (severity)
+  LOG_PREFIX_ALL     = 0xf0000000  //!< all prefixes
 };
 
 /**
@@ -146,7 +146,6 @@
 
 /**
  * \ingroup logging
- * \param name a string
  *
  * Define a Log component with a specific name.
  *
@@ -166,13 +165,25 @@
  *
  * Note the closing ';' is not on the same line;  this prevents 
  * Doxygen from spuriously warning that the macro invocation is undocumented.
- 
+ *
+ * \param name a string
  */
 #define NS_LOG_COMPONENT_DEFINE(name)                           \
   static ns3::LogComponent g_log = ns3::LogComponent (name)
 
 /**
  * \ingroup logging
+ *
+ * Define a logging component with a default mask.
+ *
+ * \param name a string
+ * \param mask the default mask
+ */
+#define NS_LOG_COMPONENT_DEFINE_MASK(name, mask)                \
+  static ns3::LogComponent g_log = ns3::LogComponent (name, mask)
+
+/**
+ * \ingroup logging
  * Append the simulation time to a log message.
  */
 #define NS_LOG_APPEND_TIME_PREFIX                               \
@@ -416,22 +427,76 @@
 LogNodePrinter LogGetNodePrinter (void);
 
 
-class LogComponent {
+/**
+ * \ingroup logging
+ *
+ * A single log component configuration.
+ */
+class LogComponent
+{
 public:
-  LogComponent (const std::string & name);
-  void EnvVarCheck (const std::string & name);
-  bool IsEnabled (enum LogLevel level) const;
+  /**
+   * Constructor
+   *
+   * \param [in] name the user-visible name for this component.
+   */
+  LogComponent (const std::string & name, const enum LogLevel mask = LOG_NONE);
+  /**
+   * Check if this LogComponent is enabled for \pname{level}
+   *
+   * \param [in] level the level to check for.
+   * \return true if \pname{level} is enabled.
+   */
+  bool IsEnabled (const enum LogLevel level) const;
+  /**
+   * Check if all levels are disabled.
+   *
+   * \return true if all levels are disabled.
+   */
   bool IsNoneEnabled (void) const;
-  void Enable (enum LogLevel level);
-  void Disable (enum LogLevel level);
+  /**
+   * Enable this LogComponent at \pname{level}
+   *
+   * \param [in] level the LogLevel to enable.
+   */
+  void Enable (const enum LogLevel level);
+  /**
+   * Disable logging at \pname{level} for this LogComponent.
+   *
+   * \param [in] level the LogLevel to disable.
+   */
+  void Disable (const enum LogLevel level);
+  /**
+   * Get the name of this LogComponent.
+   *
+   * \return the name of this LogComponent.
+   */
   char const *Name (void) const;
-  std::string GetLevelLabel(const enum LogLevel level) const;
+  /**
+   * Get the string label for the given LogLevel.
+   *
+   * \param [in] level the LogLevel to get the label for.
+   * \return the string label for \pname{level}
+   */
+  static std::string GetLevelLabel(const enum LogLevel level);
+  /**
+   * Prevent the enabling of a specific LogLevel.
+   *
+   * \param level the LogLevel to block
+   */
+  void SetMask (const enum LogLevel level);
 private:
-  int32_t     m_levels;
-  std::string m_name;
-};
+  /**
+   * Parse the `NS_LOG` environment variable for options relating to this
+   * LogComponent.
+   */
+  void EnvVarCheck (void);
   
-class ParameterLogger : public std::ostream
+  int32_t     m_levels;  //!< Enabled LogLevels
+  int32_t     m_mask;    //!< Blocked LogLevels
+  std::string m_name;    //!< LogComponent name
+
+};  // class LogComponent
 
 /**
  * \ingroup logging
--- a/src/core/model/time.cc	Fri Feb 21 16:25:43 2014 -0800
+++ b/src/core/model/time.cc	Fri Feb 21 16:27:43 2014 -0800
@@ -32,7 +32,7 @@
 #include <iomanip>  // showpos
 #include <sstream>
 
-NS_LOG_COMPONENT_DEFINE ("Time");
+NS_LOG_COMPONENT_DEFINE_MASK ("Time", ns3::LOG_PREFIX_TIME);
 
 namespace ns3 {
 
--- a/src/core/model/unix-system-mutex.cc	Fri Feb 21 16:25:43 2014 -0800
+++ b/src/core/model/unix-system-mutex.cc	Fri Feb 21 16:27:43 2014 -0800
@@ -27,7 +27,7 @@
 #include "log.h"
 
 
-NS_LOG_COMPONENT_DEFINE ("SystemMutex");
+NS_LOG_COMPONENT_DEFINE_MASK ("SystemMutex", ns3::LOG_PREFIX_TIME);
 
 namespace ns3 {