You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by jp...@apache.org on 2015/01/15 07:03:19 UTC

trafficserver git commit: TS-3297: encapsulate configuration parse errors

Repository: trafficserver
Updated Branches:
  refs/heads/master 7052d85c3 -> 70cc2d4ce


TS-3297: encapsulate configuration parse errors

Rather than returning malloc'ed strings, return and error object
that contains a formatted message.

Coverity CID #1242340
Coverity CID #1196486


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/70cc2d4c
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/70cc2d4c
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/70cc2d4c

Branch: refs/heads/master
Commit: 70cc2d4ce1762b182dd52f43a6313c61772c3a8a
Parents: 7052d85
Author: James Peach <jp...@apache.org>
Authored: Fri Jan 9 17:02:28 2015 -0800
Committer: James Peach <jp...@apache.org>
Committed: Wed Jan 14 22:02:40 2015 -0800

----------------------------------------------------------------------
 CHANGES                          |   2 +
 iocore/dns/P_SplitDNSProcessor.h |   2 +-
 iocore/dns/SplitDNS.cc           |  27 ++----
 lib/ts/MatcherUtils.cc           |  21 ++++-
 lib/ts/MatcherUtils.h            |  36 ++++++++
 lib/ts/Regression.h              |   7 --
 proxy/CacheControl.cc            |  27 ++----
 proxy/CacheControl.h             |   2 +-
 proxy/ControlMatcher.cc          | 151 ++++++++++++++++------------------
 proxy/ControlMatcher.h           |  15 +++-
 proxy/ParentSelection.cc         |  20 ++---
 proxy/ParentSelection.h          |   2 +-
 proxy/congest/Congestion.cc      |  35 +++-----
 proxy/congest/Congestion.h       |   4 +-
 14 files changed, 176 insertions(+), 175 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/70cc2d4c/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index 3278f2f..a005672 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache Traffic Server 5.3.0
 
+  *) [TS-3297] Begin encapsulating parse errors in an error object.
+
   *) [TS-3296] Use Regex.h to find PCRE headers.
 
   *) [TS-3295] Remove obsolete Compatability.h header.

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/70cc2d4c/iocore/dns/P_SplitDNSProcessor.h
----------------------------------------------------------------------
diff --git a/iocore/dns/P_SplitDNSProcessor.h b/iocore/dns/P_SplitDNSProcessor.h
index b2559ad..bc06c87 100644
--- a/iocore/dns/P_SplitDNSProcessor.h
+++ b/iocore/dns/P_SplitDNSProcessor.h
@@ -208,7 +208,7 @@ public:
   SplitDNSRecord();
   ~SplitDNSRecord();
 
-  char *Init(matcher_line * line_info);
+  config_parse_error Init(matcher_line * line_info);
 
   const char *ProcessDNSHosts(char *val);
   const char *ProcessDomainSrchList(char *val);

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/70cc2d4c/iocore/dns/SplitDNS.cc
----------------------------------------------------------------------
diff --git a/iocore/dns/SplitDNS.cc b/iocore/dns/SplitDNS.cc
index e632880..3e87a83 100644
--- a/iocore/dns/SplitDNS.cc
+++ b/iocore/dns/SplitDNS.cc
@@ -455,12 +455,10 @@ SplitDNSRecord::ProcessDomainSrchList(char *val)
    matcher_line* line_info - contains parsed label/value pairs
    of the current split.config line
    -------------------------------------------------------------- */
-char *
+config_parse_error
 SplitDNSRecord::Init(matcher_line * line_info)
 {
   const char *errPtr = NULL;
-  const int errBufLen = 1024;
-  char *errBuf = (char *)ats_malloc(errBufLen * sizeof(char));
   const char *tmp;
   char *label;
   char *val;
@@ -476,8 +474,7 @@ SplitDNSRecord::Init(matcher_line * line_info)
 
     if (strcasecmp(label, "def_domain") == 0) {
       if (NULL != (errPtr = ProcessDefDomain(val))) {
-        snprintf(errBuf, errBufLen, "%s %s at line %d", modulePrefix, errPtr, line_num);
-        return errBuf;
+        return config_parse_error("%s %s at line %d", modulePrefix, errPtr, line_num);
       }
       line_info->line[0][i] = NULL;
       line_info->num_el--;
@@ -486,8 +483,7 @@ SplitDNSRecord::Init(matcher_line * line_info)
 
     if (strcasecmp(label, "search_list") == 0) {
       if (NULL != (errPtr = ProcessDomainSrchList(val))) {
-        snprintf(errBuf, errBufLen, "%s %s at line %d", modulePrefix, errPtr, line_num);
-        return errBuf;
+        return config_parse_error("%s %s at line %d", modulePrefix, errPtr, line_num);
       }
       line_info->line[0][i] = NULL;
       line_info->num_el--;
@@ -496,8 +492,7 @@ SplitDNSRecord::Init(matcher_line * line_info)
 
     if (strcasecmp(label, "named") == 0) {
       if (NULL != (errPtr = ProcessDNSHosts(val))) {
-        snprintf(errBuf, errBufLen, "%s %s at line %d", modulePrefix, errPtr, line_num);
-        return errBuf;
+        return config_parse_error("%s %s at line %d", modulePrefix, errPtr, line_num);
       }
       line_info->line[0][i] = NULL;
       line_info->num_el--;
@@ -506,8 +501,7 @@ SplitDNSRecord::Init(matcher_line * line_info)
   }
 
   if (!ats_is_ip(&m_servers.x_server_ip[0].sa)) {
-    snprintf(errBuf, errBufLen, "%s No server specified in splitdns.config at line %d", modulePrefix, line_num);
-    return errBuf;
+    return config_parse_error("%s No server specified in splitdns.config at line %d", modulePrefix, line_num);
   }
 
   DNSHandler *dnsH = new DNSHandler;
@@ -517,11 +511,10 @@ SplitDNSRecord::Init(matcher_line * line_info)
   if ((-1 == ink_res_init(res, m_servers.x_server_ip, m_dnsSrvr_cnt,
                           m_servers.x_def_domain, m_servers.x_domain_srch_list, NULL))) {
     char ab[INET6_ADDRPORTSTRLEN];
-    snprintf(errBuf, errBufLen,
+    return config_parse_error(
       "Failed to build res record for the servers %s ...",
       ats_ip_ntop(&m_servers.x_server_ip[0].sa, ab, sizeof ab)
     );
-    return errBuf;
   }
 
   dnsH->m_res = res;
@@ -539,15 +532,11 @@ SplitDNSRecord::Init(matcher_line * line_info)
   if (line_info->num_el > 0) {
     tmp = ProcessModifiers(line_info);
     if (tmp != NULL) {
-      snprintf(errBuf, errBufLen, "%s %s at line %d in splitdns.config", modulePrefix, tmp, line_num);
-      return errBuf;
+      return config_parse_error("%s %s at line %d in splitdns.config", modulePrefix, tmp, line_num);
     }
   }
 
-  if (errBuf)
-    ats_free(errBuf);
-
-  return NULL;
+  return config_parse_error();
 }
 
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/70cc2d4c/lib/ts/MatcherUtils.cc
----------------------------------------------------------------------
diff --git a/lib/ts/MatcherUtils.cc b/lib/ts/MatcherUtils.cc
index 0ef3e4f..1a47f4c 100644
--- a/lib/ts/MatcherUtils.cc
+++ b/lib/ts/MatcherUtils.cc
@@ -31,6 +31,23 @@
 
 #include "libts.h"      /* MAGIC_EDITING_TAG */
 
+config_parse_error::config_parse_error(const char * fmt, ...)
+{
+  va_list ap;
+  int num;
+
+  va_start(ap, fmt);
+  num = vsnprintf(NULL, 0, fmt, ap);
+  va_end(ap);
+
+  this->msg = (char *)ats_malloc(num + 1);
+
+  va_start(ap, fmt);
+  num = vsnprintf(&this->msg[0], num + 1, fmt, ap);
+  va_end(ap);
+}
+
+
 // char* readIntoBuffer(const char* file_path, const char* module_name,
 //                          int* read_size_ptr)
 //
@@ -570,9 +587,9 @@ parseConfigLine(char *line, matcher_line *p_line, const matcher_tags * tags)
         // Check to see if this second destination specifier
         if (p_line->type != MATCH_NONE) {
           if (tags->dest_error_msg == false) {
-            return "Muliple Sources Specified";
+            return "Multiple Sources Specified";
           } else {
-            return "Muliple Destinations Specified";
+            return "Multiple Destinations Specified";
           }
         } else {
           p_line->dest_entry = num_el;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/70cc2d4c/lib/ts/MatcherUtils.h
----------------------------------------------------------------------
diff --git a/lib/ts/MatcherUtils.h b/lib/ts/MatcherUtils.h
index debaebb..10c8cc1 100644
--- a/lib/ts/MatcherUtils.h
+++ b/lib/ts/MatcherUtils.h
@@ -115,6 +115,42 @@ extern const matcher_tags socks_server_tags;
 
 const char *parseConfigLine(char *line, matcher_line * p_line, const matcher_tags * tags);
 
+struct config_parse_error
+{
+  config_parse_error() {
+  }
+
+  config_parse_error(const config_parse_error& rhs) {
+    if (rhs.msg.get()) {
+      this->msg = ats_strdup(rhs.msg.get());
+    }
+  }
+
+  config_parse_error(const char * fmt, ...) TS_PRINTFLIKE(2, 3);
+
+  config_parse_error& operator=(const config_parse_error& rhs) {
+    if (rhs.msg.get()) {
+      this->msg = ats_strdup(rhs.msg.get());
+    } else {
+      this->msg = (char *)NULL;
+    }
+
+    return *this;
+  }
+
+  const char * get() const {
+    return msg.get();
+  }
+
+  // A config error object evaluates to true if there is an error message.
+  operator bool() const {
+    return msg.get() != NULL;
+  }
+
+private:
+  ats_scoped_str msg;
+};
+
 // inline void LowerCaseStr(char* str)
 //
 //   Modifies str so all characters are lower

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/70cc2d4c/lib/ts/Regression.h
----------------------------------------------------------------------
diff --git a/lib/ts/Regression.h b/lib/ts/Regression.h
index 1a6486b..189abe5 100644
--- a/lib/ts/Regression.h
+++ b/lib/ts/Regression.h
@@ -101,11 +101,4 @@ char *regression_status_string(int status);
 
 extern int regression_level;
 
-#define SignalError(_buf, _already)                                     \
-{                                                                       \
-  if(_already == false) pmgmt->signalManager(MGMT_SIGNAL_CONFIG_ERROR, _buf); \
-  _already = true;                                                      \
-  Warning("%s", _buf);                                                  \
-}                                                                       \
-
 #endif /* _Regression_h */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/70cc2d4c/proxy/CacheControl.cc
----------------------------------------------------------------------
diff --git a/proxy/CacheControl.cc b/proxy/CacheControl.cc
index efadab0..b655bd3 100644
--- a/proxy/CacheControl.cc
+++ b/proxy/CacheControl.cc
@@ -256,7 +256,7 @@ CacheControlRecord::Print()
   ControlBase::Print();
 }
 
-// bool CacheControlRecord::Init(matcher_line* line_info)
+// config_parse_error CacheControlRecord::Init(matcher_line* line_info)
 //
 //    matcher_line* line_info - contains parsed label/value
 //      pairs of the current cache.config line
@@ -265,12 +265,10 @@ CacheControlRecord::Print()
 //      Otherwise, returns an error string that the caller MUST
 //        DEALLOCATE with free()
 //
-char *
+config_parse_error
 CacheControlRecord::Init(matcher_line * line_info)
 {
   int time_in;
-  char *errBuf;
-  const int errBufLen = 1024;
   const char *tmp;
   char *label;
   char *val;
@@ -289,10 +287,7 @@ CacheControlRecord::Init(matcher_line * line_info)
       char* ptr = 0;
       int v = strtol(val, &ptr, 0);
       if (!ptr || v < 0 || v > 4) {
-        errBuf = static_cast<char*>(ats_malloc(errBufLen * sizeof(char)));
-        snprintf(errBuf, errBufLen, "Value for " TWEAK_CACHE_RESPONSES_TO_COOKIES
-                 " must be an integer in the range 0..4");
-        return errBuf;
+        return config_parse_error("Value for " TWEAK_CACHE_RESPONSES_TO_COOKIES " must be an integer in the range 0..4");
       } else {
         cache_responses_to_cookies = v;
       }
@@ -335,9 +330,7 @@ CacheControlRecord::Init(matcher_line * line_info)
         directive = CC_IGNORE_SERVER_NO_CACHE;
         d_found = true;
       } else {
-        errBuf = (char *)ats_malloc(errBufLen * sizeof(char));
-        snprintf(errBuf, errBufLen, "%s Invalid action at line %d in cache.config", modulePrefix, line_num);
-        return errBuf;
+        return config_parse_error("%s Invalid action at line %d in cache.config", modulePrefix, line_num);
       }
     } else {
 
@@ -358,9 +351,7 @@ CacheControlRecord::Init(matcher_line * line_info)
           this->time_arg = time_in;
 
         } else {
-          errBuf = (char *)ats_malloc(errBufLen * sizeof(char));
-          snprintf(errBuf, errBufLen, "%s %s at line %d in cache.config", modulePrefix, tmp, line_num);
-          return errBuf;
+          return config_parse_error("%s %s at line %d in cache.config", modulePrefix, tmp, line_num);
         }
       }
     }
@@ -374,18 +365,14 @@ CacheControlRecord::Init(matcher_line * line_info)
   }
 
   if (d_found == false) {
-    errBuf = (char *)ats_malloc(errBufLen * sizeof(char));
-    snprintf(errBuf, errBufLen, "%s No directive in cache.config at line %d", modulePrefix, line_num);
-    return errBuf;
+    return config_parse_error("%s No directive in cache.config at line %d", modulePrefix, line_num);
   }
   // Process any modifiers to the directive, if they exist
   if (line_info->num_el > 0) {
     tmp = ProcessModifiers(line_info);
 
     if (tmp != NULL) {
-      errBuf = (char *)ats_malloc(errBufLen * sizeof(char));
-      snprintf(errBuf, errBufLen, "%s %s at line %d in cache.config", modulePrefix, tmp, line_num);
-      return errBuf;
+      return config_parse_error("%s %s at line %d in cache.config", modulePrefix, tmp, line_num);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/70cc2d4c/proxy/CacheControl.h
----------------------------------------------------------------------
diff --git a/proxy/CacheControl.h b/proxy/CacheControl.h
index 1bbe380..c5a5e75 100644
--- a/proxy/CacheControl.h
+++ b/proxy/CacheControl.h
@@ -127,7 +127,7 @@ public:
   CacheControlType directive;
   int time_arg;
   int cache_responses_to_cookies;
-  char *Init(matcher_line * line_info);
+  config_parse_error Init(matcher_line * line_info);
   inkcoreapi void UpdateMatch(CacheControlResult * result, RequestData * rdata);
   void Print();
 };

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/70cc2d4c/proxy/ControlMatcher.cc
----------------------------------------------------------------------
diff --git a/proxy/ControlMatcher.cc b/proxy/ControlMatcher.cc
index 226e136..be01d05 100644
--- a/proxy/ControlMatcher.cc
+++ b/proxy/ControlMatcher.cc
@@ -48,8 +48,6 @@
  *   Place all template instantiations at the bottom of the file
  ****************************************************************/
 
-
-
 // HttpRequestData accessors
 //   Can not be inlined due being virtual functions
 //
@@ -174,7 +172,7 @@ template<class Data, class Result> void HostMatcher<Data, Result>::Match(Request
 }
 
 //
-// char* HostMatcher<Data,Result>::NewEntry(bool domain_record,
+// config_parse_error HostMatcher<Data,Result>::NewEntry(bool domain_record,
 //          char* match_data, char* match_info, int line_num)
 //
 //   Creates a new host/domain record
@@ -183,10 +181,11 @@ template<class Data, class Result> void HostMatcher<Data, Result>::Match(Request
 //   If not, returns a pointer to malloc allocated error string
 //     that the caller MUST DEALLOCATE
 //
-template<class Data, class Result> char *HostMatcher<Data, Result>::NewEntry(matcher_line * line_info)
+template<class Data, class Result> config_parse_error
+HostMatcher<Data, Result>::NewEntry(matcher_line * line_info)
 {
   Data *cur_d;
-  char *errBuf;
+  config_parse_error error;
   char *match_data;
 
   // Make sure space has been allocated
@@ -208,18 +207,17 @@ template<class Data, class Result> char *HostMatcher<Data, Result>::NewEntry(mat
 
   // Fill in the parameter info
   cur_d = data_array + num_el;
-  errBuf = cur_d->Init(line_info);
-
-  if (errBuf != NULL) {
+  error = cur_d->Init(line_info);
+  if (error) {
     // There was a problem so undo the effects this function
     memset(cur_d, 0, sizeof(Data));
-    return errBuf;
+  } else {
+    // Fill in the matching info
+    host_lookup->NewEntry(match_data, (line_info->type == MATCH_DOMAIN) ? true : false, cur_d);
+    num_el++;
   }
-  // Fill in the matching info
-  host_lookup->NewEntry(match_data, (line_info->type == MATCH_DOMAIN) ? true : false, cur_d);
 
-  num_el++;
-  return NULL;
+  return error;
 }
 
 /*************************************************************
@@ -231,6 +229,10 @@ template<class Data, class Result> char *HostMatcher<Data, Result>::NewEntry(mat
 //
 template<class Data, class Result> UrlMatcher<Data, Result>::UrlMatcher(const char *name, const char *filename)
   : url_ht(NULL),
+    url_str(NULL),
+    url_value(NULL),
+    data_array(NULL),
+    array_len(0),
     num_el(-1),
     matcher_name(name),
     file_name(filename)
@@ -283,14 +285,15 @@ template<class Data, class Result> void UrlMatcher<Data, Result>::AllocateSpace(
 }
 
 //
-// char* UrlMatcher<Data,Result>::NewEntry(matcher_line* line_info)
+// config_parse_error UrlMatcher<Data,Result>::NewEntry(matcher_line* line_info)
 //
-template<class Data, class Result> char *UrlMatcher<Data, Result>::NewEntry(matcher_line * line_info)
+template<class Data, class Result> config_parse_error
+UrlMatcher<Data, Result>::NewEntry(matcher_line * line_info)
 {
   Data *cur_d;
-  char *errBuf;
   char *pattern;
   int *value;
+  config_parse_error error;
 
   // Make sure space has been allocated
   ink_assert(num_el >= 0);
@@ -305,11 +308,7 @@ template<class Data, class Result> char *UrlMatcher<Data, Result>::NewEntry(matc
   ink_assert(pattern != NULL);
 
   if (ink_hash_table_lookup(url_ht, pattern, (void **)&value)) {
-    errBuf = (char *)ats_malloc(1024 * sizeof(char));
-    *errBuf = '\0';
-    snprintf(errBuf, 1024, "%s url expression error(have exist) at line %d position",
-                 matcher_name, line_info->line_num);
-    return errBuf;
+    return config_parse_error("%s url expression error (have exist) at line %d position", matcher_name, line_info->line_num);
   }
 
   // Remove our consumed label from the parsed line
@@ -318,15 +317,15 @@ template<class Data, class Result> char *UrlMatcher<Data, Result>::NewEntry(matc
 
   // Fill in the parameter info
   cur_d = data_array + num_el;
-  errBuf = cur_d->Init(line_info);
-
-  if (errBuf == NULL) {
+  error = cur_d->Init(line_info);
+  if (error) {
     url_str[num_el] = ats_strdup(pattern);
     url_value[num_el] = num_el;
     ink_hash_table_insert(url_ht, url_str[num_el], (void *)&url_value[num_el]);
     num_el++;
   }
-  return errBuf;
+
+  return error;
 }
 
 //
@@ -425,15 +424,16 @@ template<class Data, class Result> void RegexMatcher<Data, Result>::AllocateSpac
 }
 
 //
-// char* RegexMatcher<Data,Result>::NewEntry(matcher_line* line_info)
+// config_parse_error RegexMatcher<Data,Result>::NewEntry(matcher_line* line_info)
 //
-template<class Data, class Result> char *RegexMatcher<Data, Result>::NewEntry(matcher_line * line_info)
+template<class Data, class Result> config_parse_error
+RegexMatcher<Data, Result>::NewEntry(matcher_line * line_info)
 {
   Data *cur_d;
-  char *errBuf;
   char *pattern;
-  const char *error;
+  const char *errptr;
   int erroffset;
+  config_parse_error error;
 
   // Make sure space has been allocated
   ink_assert(num_el >= 0);
@@ -448,14 +448,10 @@ template<class Data, class Result> char *RegexMatcher<Data, Result>::NewEntry(ma
   ink_assert(pattern != NULL);
 
   // Create the compiled regular expression
-  re_array[num_el] = pcre_compile(pattern, 0, &error, &erroffset, NULL);
+  re_array[num_el] = pcre_compile(pattern, 0, &errptr, &erroffset, NULL);
   if (!re_array[num_el]) {
-    errBuf = (char *)ats_malloc(1024 * sizeof(char));
-    *errBuf = '\0';
-    snprintf(errBuf, 1024, "%s regular expression error at line %d position %d : %s",
-                 matcher_name, line_info->line_num, erroffset, error);
-    re_array[num_el] = NULL;
-    return errBuf;
+    return config_parse_error("%s regular expression error at line %d position %d : %s",
+                 matcher_name, line_info->line_num, erroffset, errptr);
   }
   re_str[num_el] = ats_strdup(pattern);
 
@@ -465,19 +461,19 @@ template<class Data, class Result> char *RegexMatcher<Data, Result>::NewEntry(ma
 
   // Fill in the parameter info
   cur_d = data_array + num_el;
-  errBuf = cur_d->Init(line_info);
+  error = cur_d->Init(line_info);
 
-  if (errBuf == NULL) {
-    num_el++;
-  } else {
+  if (error) {
     // There was a problem so undo the effects this function
     ats_free(re_str[num_el]);
     re_str[num_el] = NULL;
     pcre_free(re_array[num_el]);
     re_array[num_el] = NULL;
+  } else {
+    num_el++;
   }
 
-  return errBuf;
+  return error;
 }
 
 //
@@ -605,7 +601,7 @@ template<class Data, class Result> void IpMatcher<Data, Result>::AllocateSpace(i
 }
 
 //
-// char* IpMatcher<Data,Result>::NewEntry(matcher_line* line_info)
+// config_parse_error IpMatcher<Data,Result>::NewEntry(matcher_line* line_info)
 //
 //    Inserts a range the ip lookup table.
 //        Creates new table levels as needed
@@ -614,14 +610,14 @@ template<class Data, class Result> void IpMatcher<Data, Result>::AllocateSpace(i
 //     allocated error string which the CALLEE is responsible
 //     for deallocating
 //
-template<class Data, class Result> char *IpMatcher<Data, Result>::NewEntry(matcher_line * line_info)
+template<class Data, class Result> config_parse_error
+IpMatcher<Data, Result>::NewEntry(matcher_line * line_info)
 {
-
   Data *cur_d;
-  const char *errPtr;
-  char *errBuf;
+  const char *errptr;
   char *match_data;
   IpEndpoint addr1, addr2;
+  config_parse_error error;
 
   // Make sure space has been allocated
   ink_assert(num_el >= 0);
@@ -637,12 +633,9 @@ template<class Data, class Result> char *IpMatcher<Data, Result>::NewEntry(match
   ink_assert(match_data != NULL);
 
   // Extract the IP range
-  errPtr = ExtractIpRange(match_data, &addr1.sa, &addr2.sa);
-  if (errPtr != NULL) {
-    const size_t errorSize = 1024;
-    errBuf = (char *)ats_malloc(errorSize * sizeof(char));
-    snprintf(errBuf, errorSize, "%s %s at %s line %d", matcher_name, errPtr, file_name, line_info->line_num);
-    return errBuf;
+  errptr = ExtractIpRange(match_data, &addr1.sa, &addr2.sa);
+  if (errptr != NULL) {
+    return config_parse_error("%s %s at %s line %d", matcher_name, errptr, file_name, line_info->line_num);
   }
 
   // Remove our consumed label from the parsed line
@@ -651,15 +644,13 @@ template<class Data, class Result> char *IpMatcher<Data, Result>::NewEntry(match
 
   // Fill in the parameter info
   cur_d = data_array + num_el;
-  errBuf = cur_d->Init(line_info);
-  if (errBuf != NULL) {
-    return errBuf;
+  error = cur_d->Init(line_info);
+  if (!error) {
+    ip_map.mark(&addr1.sa, &addr2.sa, cur_d);
+    ++num_el;
   }
 
-  ip_map.mark(&addr1.sa, &addr2.sa, cur_d);
-
-  ++num_el;
-  return NULL;
+  return error;
 }
 
 //
@@ -782,14 +773,13 @@ template<class Data, class Result> void ControlMatcher<Data, Result>::Match(Requ
   }
 }
 
-int fstat_wrapper(int fd, struct stat *s);
-
 // int ControlMatcher::BuildTable() {
 //
 //    Reads the cache.config file and build the records array
 //      from it
 //
-template<class Data, class Result> int ControlMatcher<Data, Result>::BuildTableFromString(char *file_buf)
+template<class Data, class Result> int
+ControlMatcher<Data, Result>::BuildTableFromString(char *file_buf)
 {
   // Table build locals
   Tokenizer bufTok("\n");
@@ -802,8 +792,6 @@ template<class Data, class Result> int ControlMatcher<Data, Result>::BuildTableF
   int second_pass = 0;
   int numEntries = 0;
   bool alarmAlready = false;
-  char errBuf[1024];
-  const char *errPtr = NULL;
 
   // type counts
   int hostDomain = 0;
@@ -828,15 +816,15 @@ template<class Data, class Result> int ControlMatcher<Data, Result>::BuildTableF
     }
 
     if (*tmp != '#' && *tmp != '\0') {
+      const char * errptr;
 
       current = (matcher_line *)ats_malloc(sizeof(matcher_line));
-      errPtr = parseConfigLine((char *) tmp, current, config_tags);
+      errptr = parseConfigLine((char *) tmp, current, config_tags);
 
-      if (errPtr != NULL) {
+      if (errptr != NULL) {
         if (config_tags != &socks_server_tags) {
-          snprintf(errBuf, sizeof(errBuf), "%s discarding %s entry at line %d : %s",
-                   matcher_name, config_file_path, line_num, errPtr);
-          SignalError(errBuf, alarmAlready);
+          config_parse_error error("%s discarding %s entry at line %d : %s", matcher_name, config_file_path, line_num, errptr);
+          SignalError(error.get(), alarmAlready);
         }
         ats_free(current);
       } else {
@@ -913,33 +901,32 @@ template<class Data, class Result> int ControlMatcher<Data, Result>::BuildTableF
   // Traverse the list and build the records table
   current = first;
   while (current != NULL) {
+    config_parse_error error;
+
     second_pass++;
     if ((flags & ALLOW_HOST_TABLE) && current->type == MATCH_DOMAIN) {
-      errPtr = hostMatch->NewEntry(current);
+      error = hostMatch->NewEntry(current);
     } else if ((flags & ALLOW_HOST_TABLE) && current->type == MATCH_HOST) {
-      errPtr = hostMatch->NewEntry(current);
+      error = hostMatch->NewEntry(current);
     } else if ((flags & ALLOW_REGEX_TABLE) && current->type == MATCH_REGEX) {
-      errPtr = reMatch->NewEntry(current);
+      error = reMatch->NewEntry(current);
     } else if ((flags & ALLOW_URL_TABLE) && current->type == MATCH_URL) {
-      errPtr = urlMatch->NewEntry(current);
+      error = urlMatch->NewEntry(current);
     } else if ((flags & ALLOW_IP_TABLE) && current->type == MATCH_IP) {
-      errPtr = ipMatch->NewEntry(current);
+      error = ipMatch->NewEntry(current);
     } else if ((flags & ALLOW_HOST_REGEX_TABLE) && current->type == MATCH_HOST_REGEX) {
-      errPtr = hrMatch->NewEntry(current);
+      error = hrMatch->NewEntry(current);
     } else {
-      errPtr = NULL;
-      snprintf(errBuf, sizeof(errBuf), "%s discarding %s entry with unknown type at line %d",
+      error = config_parse_error("%s discarding %s entry with unknown type at line %d",
                matcher_name, config_file_path, current->line_num);
-      SignalError(errBuf, alarmAlready);
     }
 
     // Check to see if there was an error in creating
     //   the NewEntry
-    if (errPtr != NULL) {
-      SignalError(errPtr, alarmAlready);
-      //ats_free(errPtr); // XXX - why are we trying to free
-      errPtr = NULL;
+    if (error) {
+      SignalError(error.get(), alarmAlready);
     }
+
     // Deallocate the parsing structure
     last = current;
     current = current->next;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/70cc2d4c/proxy/ControlMatcher.h
----------------------------------------------------------------------
diff --git a/proxy/ControlMatcher.h b/proxy/ControlMatcher.h
index 2ec4b9d..915a980 100644
--- a/proxy/ControlMatcher.h
+++ b/proxy/ControlMatcher.h
@@ -99,6 +99,13 @@
 #include <ctype.h>
 #endif
 
+#define SignalError(_buf, _already)                                     \
+{                                                                       \
+  if(_already == false) pmgmt->signalManager(MGMT_SIGNAL_CONFIG_ERROR, _buf); \
+  _already = true;                                                      \
+  Warning("%s", _buf);                                                  \
+}                                                                       \
+
 class HostLookup;
 struct HttpApiInfo;
 struct matcher_line;
@@ -162,7 +169,7 @@ public:
   ~UrlMatcher();
   void Match(RequestData * rdata, Result * result);
   void AllocateSpace(int num_entries);
-  char *NewEntry(matcher_line * line_info);
+  config_parse_error NewEntry(matcher_line * line_info);
   void Print();
 
   int getNumElements() { return num_el; }
@@ -186,7 +193,7 @@ public:
   ~RegexMatcher();
   void Match(RequestData * rdata, Result * result);
   void AllocateSpace(int num_entries);
-  char *NewEntry(matcher_line * line_info);
+  config_parse_error NewEntry(matcher_line * line_info);
   void Print();
 
   int getNumElements() { return num_el; }
@@ -214,7 +221,7 @@ public:
   ~HostMatcher();
   void Match(RequestData * rdata, Result * result);
   void AllocateSpace(int num_entries);
-  char *NewEntry(matcher_line * line_info);
+  config_parse_error NewEntry(matcher_line * line_info);
   void Print();
 
   int getNumElements() { return num_el; }
@@ -237,7 +244,7 @@ public:
   ~IpMatcher();
   void Match(sockaddr const* ip_addr, RequestData * rdata, Result * result);
   void AllocateSpace(int num_entries);
-  char *NewEntry(matcher_line * line_info);
+  config_parse_error NewEntry(matcher_line * line_info);
   void Print();
 
   int getNumElements() { return num_el; }

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/70cc2d4c/proxy/ParentSelection.cc
----------------------------------------------------------------------
diff --git a/proxy/ParentSelection.cc b/proxy/ParentSelection.cc
index 262cf26..c1dc646 100644
--- a/proxy/ParentSelection.cc
+++ b/proxy/ParentSelection.cc
@@ -817,7 +817,7 @@ ParentRecord::buildConsistentHash(void) {
   }
 }
 
-// char* ParentRecord::Init(matcher_line* line_info)
+// config_parse_error ParentRecord::Init(matcher_line* line_info)
 //
 //    matcher_line* line_info - contains parsed label/value
 //      pairs of the current cache.config line
@@ -826,12 +826,10 @@ ParentRecord::buildConsistentHash(void) {
 //      Otherwise, returns an error string that the caller MUST
 //        DEALLOCATE with ats_free()
 //
-char *
+config_parse_error
 ParentRecord::Init(matcher_line * line_info)
 {
   const char *errPtr = NULL;
-  char *errBuf;
-  const int errBufLen = 1024;
   const char *tmp;
   char *label;
   char *val;
@@ -884,9 +882,7 @@ ParentRecord::Init(matcher_line * line_info)
     }
     // Report errors generated by ProcessParents();
     if (errPtr != NULL) {
-      errBuf = (char *)ats_malloc(errBufLen * sizeof(char));
-      snprintf(errBuf, errBufLen, "%s %s at line %d", modulePrefix, errPtr, line_num);
-      return errBuf;
+      return config_parse_error("%s %s at line %d", modulePrefix, errPtr, line_num);
     }
 
     if (used == true) {
@@ -897,18 +893,14 @@ ParentRecord::Init(matcher_line * line_info)
   }
 
   if (this->parents == NULL && go_direct == false) {
-    errBuf = (char *)ats_malloc(errBufLen * sizeof(char));
-    snprintf(errBuf, errBufLen, "%s No parent specified in parent.config at line %d", modulePrefix, line_num);
-    return errBuf;
+    return config_parse_error("%s No parent specified in parent.config at line %d", modulePrefix, line_num);
   }
   // Process any modifiers to the directive, if they exist
   if (line_info->num_el > 0) {
     tmp = ProcessModifiers(line_info);
 
     if (tmp != NULL) {
-      errBuf = (char *)ats_malloc(errBufLen * sizeof(char));
-      snprintf(errBuf, errBufLen, "%s %s at line %d in parent.config", modulePrefix, tmp, line_num);
-      return errBuf;
+      return config_parse_error("%s %s at line %d in parent.config", modulePrefix, tmp, line_num);
     }
     // record SCHEME modifier if present.
     // NULL if not present
@@ -921,7 +913,7 @@ ParentRecord::Init(matcher_line * line_info)
     }
   }
 
-  return NULL;
+  return config_parse_error();
 }
 
 // void ParentRecord::UpdateMatch(ParentResult* result, RequestData* rdata);

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/70cc2d4c/proxy/ParentSelection.h
----------------------------------------------------------------------
diff --git a/proxy/ParentSelection.h b/proxy/ParentSelection.h
index e02bcc9..3a50146 100644
--- a/proxy/ParentSelection.h
+++ b/proxy/ParentSelection.h
@@ -195,7 +195,7 @@ public:
 
   ~ParentRecord();
 
-  char *Init(matcher_line *line_info);
+  config_parse_error Init(matcher_line *line_info);
   bool DefaultInit(char *val);
   void UpdateMatch(ParentResult *result, RequestData *rdata);
   void FindParent(bool firstCall, ParentResult *result, RequestData *rdata, ParentConfigParams *config);

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/70cc2d4c/proxy/congest/Congestion.cc
----------------------------------------------------------------------
diff --git a/proxy/congest/Congestion.cc b/proxy/congest/Congestion.cc
index 1ab17a0..2b067a3 100644
--- a/proxy/congest/Congestion.cc
+++ b/proxy/congest/Congestion.cc
@@ -136,19 +136,14 @@ CongestionControlRecord::setdefault()
   max_connection = DEFAULT_max_connection;
 }
 
-char *
+config_parse_error
 CongestionControlRecord::validate()
 {
-  char *error_buf = NULL;
-  int error_len = 1024;
-
 #define IsGt0(var)\
   if ( var < 1 ) { \
-    error_buf = (char*)ats_malloc(error_len); \
-    snprintf(error_buf, error_len, "line %d: invalid %s = %d, %s must > 0", \
-	    line_num, #var, var, #var); \
+    config_parse_error error("line %d: invalid %s = %d, %s must > 0", line_num, #var, var, #var); \
     cleanup(); \
-    return error_buf; \
+    return error; \
   }
 
   if (error_page == NULL)
@@ -156,11 +151,10 @@ CongestionControlRecord::validate()
   if (max_connection_failures >= CONG_RULE_MAX_max_connection_failures ||
       (max_connection_failures <= 0 && max_connection_failures != CONG_RULE_ULIMITED_max_connection_failures)
     ) {
-    error_buf = (char *)ats_malloc(error_len);
-    snprintf(error_buf, error_len, "line %d: invalid %s = %d not in [1, %d) range",
+    config_parse_error error("line %d: invalid %s = %d not in [1, %d) range",
              line_num, "max_connection_failures", max_connection_failures, CONG_RULE_MAX_max_connection_failures);
     cleanup();
-    return error_buf;
+    return error;
   }
 
   IsGt0(fail_window);
@@ -176,14 +170,13 @@ CongestionControlRecord::validate()
   // max_connection_failures <= 0 && max_connection == -1 no congestion control for the rule
   // max_connection == 0, no connection allow to the origin server for the rule
 #undef IsGt0
-  return error_buf;
+
+  return config_parse_error();
 }
 
-char *
+config_parse_error
 CongestionControlRecord::Init(matcher_line * line_info)
 {
-  char *errBuf;
-  const int errBufLen = 1024;
   const char *tmp;
   char *label;
   char *val;
@@ -250,18 +243,16 @@ CongestionControlRecord::Init(matcher_line * line_info)
     tmp = ProcessModifiers(line_info);
 
     if (tmp != NULL) {
-      errBuf = (char *)ats_malloc(errBufLen * sizeof(char));
-      snprintf(errBuf, errBufLen, "%s %s at line %d in congestion.config", congestPrefix, tmp, line_num);
-      return errBuf;
+      return config_parse_error("%s %s at line %d in congestion.config", congestPrefix, tmp, line_num);
     }
-
   }
 
-  char *err_msg = validate();
-  if (err_msg == NULL) {
+  config_parse_error error = validate();
+  if (!error) {
     pRecord = new CongestionControlRecord(*this);
   }
-  return err_msg;
+
+  return error;
 }
 
 void

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/70cc2d4c/proxy/congest/Congestion.h
----------------------------------------------------------------------
diff --git a/proxy/congest/Congestion.h b/proxy/congest/Congestion.h
index e3de2b9..4486698 100644
--- a/proxy/congest/Congestion.h
+++ b/proxy/congest/Congestion.h
@@ -64,13 +64,13 @@ public:
   CongestionControlRecord();
   CongestionControlRecord(const CongestionControlRecord & rec);
    ~CongestionControlRecord();
-  char *Init(matcher_line * line_info);
+  config_parse_error Init(matcher_line * line_info);
   void UpdateMatch(CongestionControlRule * pRule, RequestData * rdata);
   void Print();
 
   void cleanup();
   void setdefault();
-  char *validate();
+  config_parse_error validate();
 
   int rank;                     // matching preference
 /*