diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l
index 78907b9..ec001d6 100644
*** a/src/backend/utils/misc/guc-file.l
--- b/src/backend/utils/misc/guc-file.l
*************** ProcessConfigFile(GucContext context)
*** 111,135 ****
  	char	   *cvc = NULL;
  	struct config_string *cvc_struct;
  	int			i;
  
  	Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
  
! 	if (context == PGC_SIGHUP)
! 	{
! 		/*
! 		 * To avoid cluttering the log, only the postmaster bleats loudly
! 		 * about problems with the config file.
! 		 */
! 		elevel = IsUnderPostmaster ? DEBUG2 : LOG;
! 	}
! 	else
! 		elevel = ERROR;
! 
! 	/* Parse the file into a list of option names and values */
  	head = tail = NULL;
  
  	if (!ParseConfigFile(ConfigFileName, NULL, 0, elevel, &head, &tail))
! 		goto cleanup_list;
  
  	/*
  	 * We need the proposed new value of custom_variable_classes to check
--- 111,139 ----
  	char	   *cvc = NULL;
  	struct config_string *cvc_struct;
  	int			i;
+ 	bool		OK = true;
  
+ 	/* Config files are only processes on startup (by the postmaster)
+ 	 * and on SIGUP (by the postmaster and backends)
+ 	 */
  	Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
+ 	Assert(!(context == PGC_POSTMATER && IsUnderPostmaster));
  
! 	/*
! 	 * To avoid cluttering the log, only the postmaster bleats loudly
! 	 * about problems with the config file.
! 	 */
! 	elevel = IsUnderPostmaster ? DEBUG2 : LOG;
! 	
! 	/* Parse the file into a list of option names and values.
! 	 * We continue even if we hit a parse errors because we
! 	 * also want to report invalid value in the parts we
! 	 * could parse
! 	 */
  	head = tail = NULL;
  
  	if (!ParseConfigFile(ConfigFileName, NULL, 0, elevel, &head, &tail))
! 		OK = false;
  
  	/*
  	 * We need the proposed new value of custom_variable_classes to check
*************** ProcessConfigFile(GucContext context)
*** 161,167 ****
  			goto cleanup_list;
  		if (!call_string_check_hook(cvc_struct, &cvc, &extra,
  									PGC_S_FILE, elevel))
! 			goto cleanup_list;
  		if (extra)
  			free(extra);
  	}
--- 165,171 ----
  			goto cleanup_list;
  		if (!call_string_check_hook(cvc_struct, &cvc, &extra,
  									PGC_S_FILE, elevel))
! 			OK = false;
  		if (extra)
  			free(extra);
  	}
*************** ProcessConfigFile(GucContext context)
*** 201,207 ****
  						(errcode(ERRCODE_UNDEFINED_OBJECT),
  						 errmsg("unrecognized configuration parameter \"%s\"",
  								item->name)));
! 				goto cleanup_list;
  			}
  			/*
  			 * 2. There is no GUC entry.  If we called set_config_option then
--- 205,211 ----
  						(errcode(ERRCODE_UNDEFINED_OBJECT),
  						 errmsg("unrecognized configuration parameter \"%s\"",
  								item->name)));
! 				OK = false;
  			}
  			/*
  			 * 2. There is no GUC entry.  If we called set_config_option then
*************** ProcessConfigFile(GucContext context)
*** 221,228 ****
  
  		if (!set_config_option(item->name, item->value, context,
  							   PGC_S_FILE, GUC_ACTION_SET, false))
! 			goto cleanup_list;
  	}
  
  	/*
  	 * Check for variables having been removed from the config file, and
--- 225,235 ----
  
  		if (!set_config_option(item->name, item->value, context,
  							   PGC_S_FILE, GUC_ACTION_SET, false))
! 			OK = false;
  	}
+ 	/* Don't change configuration options if errors were detected earlier */
+ 	if (!OK)
+ 		goto cleanup_list;	
  
  	/*
  	 * Check for variables having been removed from the config file, and
*************** ProcessConfigFile(GucContext context)
*** 345,350 ****
--- 352,361 ----
  	FreeConfigVariables(head);
  	if (cvc)
  		free(cvc);
+ 	/* If we got an error during postmaster's start - complain and bail out */
+ 	if (!OK && context == PGC_POSTMASTER)
+ 		ereport(ERROR,
+ 				(errmsg("errors detected while parsing configuration files")));
  }
  
  /*
*************** ParseConfigFile(const char *config_file,
*** 437,442 ****
--- 448,459 ----
   * already been ereport'd, it is only necessary for the caller to clean up
   * its own state and release the name/value pairs list.
   *
+  * If elevel < ERROR then we don't return immediately on the first error,
+  * although we do return after comming across 100 of them. This is to prevent
+  * trashing out logs when parsing a completely bogus file. We consider all 
+  * parse errors in "includes" as a single one for simplicity, it's unlikely we 
+  * ever come across the bogus file with valid include directives.
+  *
   * Note: if elevel >= ERROR then an error will not return control to the
   * caller, and internal state such as open files will not be cleaned up.
   * This case occurs only during postmaster or standalone-backend startup,
*************** bool
*** 447,455 ****
  ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
  			  ConfigVariable **head_p, ConfigVariable **tail_p)
  {
- 	bool		OK = true;
  	YY_BUFFER_STATE lex_buffer;
! 	int			token;
  
  	/*
  	 * Parse
--- 464,472 ----
  ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
  			  ConfigVariable **head_p, ConfigVariable **tail_p)
  {
  	YY_BUFFER_STATE lex_buffer;
! 	int			token,
! 				errorcount;
  
  	/*
  	 * Parse
*************** ParseConfigFp(FILE *fp, const char *conf
*** 458,463 ****
--- 475,481 ----
  	yy_switch_to_buffer(lex_buffer);
  
  	ConfigFileLineno = 1;
+ 	errorcount = 0;
  
  	/* This loop iterates once per logical line */
  	while ((token = yylex()))
*************** ParseConfigFp(FILE *fp, const char *conf
*** 512,523 ****
  			if (!ParseConfigFile(opt_value, config_file,
  								 depth + 1, elevel,
  								 head_p, tail_p))
! 			{
! 				pfree(opt_name);
! 				pfree(opt_value);
! 				OK = false;
! 				goto cleanup_exit;
! 			}
  			yy_switch_to_buffer(lex_buffer);
  			ConfigFileLineno = save_ConfigFileLineno;
  			pfree(opt_name);
--- 530,536 ----
  			if (!ParseConfigFile(opt_value, config_file,
  								 depth + 1, elevel,
  								 head_p, tail_p))
! 				errorcount++;
  			yy_switch_to_buffer(lex_buffer);
  			ConfigFileLineno = save_ConfigFileLineno;
  			pfree(opt_name);
*************** ParseConfigFp(FILE *fp, const char *conf
*** 576,602 ****
  		/* break out of loop if read EOF, else loop for next line */
  		if (token == 0)
  			break;
  	}
  
  	/* successful completion of parsing */
- 	goto cleanup_exit;
- 
-  parse_error:
- 	if (token == GUC_EOL || token == 0)
- 		ereport(elevel,
- 				(errcode(ERRCODE_SYNTAX_ERROR),
- 				 errmsg("syntax error in file \"%s\" line %u, near end of line",
- 						config_file, ConfigFileLineno - 1)));
- 	else
- 		ereport(elevel,
- 				(errcode(ERRCODE_SYNTAX_ERROR),
- 				 errmsg("syntax error in file \"%s\" line %u, near token \"%s\"",
- 						config_file, ConfigFileLineno, yytext)));
- 	OK = false;
- 
- cleanup_exit:
  	yy_delete_buffer(lex_buffer);
! 	return OK;
  }
  
  
--- 589,625 ----
  		/* break out of loop if read EOF, else loop for next line */
  		if (token == 0)
  			break;
+ 		/* skip over parse_error if we made it this far without errors */
+ 		continue;
+ 	
+ 	parse_error:
+ 		if (token == GUC_EOL || token == 0)
+ 			ereport(elevel,
+ 					(errcode(ERRCODE_SYNTAX_ERROR),
+ 					 errmsg("syntax error in file \"%s\" line %u, near end of line",
+ 							config_file, ConfigFileLineno - 1)));
+ 		else
+ 			ereport(elevel,
+ 					(errcode(ERRCODE_SYNTAX_ERROR),
+ 					 errmsg("syntax error in file \"%s\" line %u, near token \"%s\"",
+ 							config_file, ConfigFileLineno, yytext)));
+ 		errorcount++;
+ 		/* fast forward till the next EOL/EOF */
+ 		while (token != 0 && token != GUC_EOL)
+ 			token = yylex();
+ 		
+ 		/* break out of loop on EOF */
+ 		if (token == 0)
+ 			break;
+ 		
+ 		/* avoid producing too much noise when parsing a bogus file */
+ 		if (errorcount >= 100)
+ 			break;
  	}
  
  	/* successful completion of parsing */
  	yy_delete_buffer(lex_buffer);
! 	return (errorcount == 0);
  }
  
  
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 92391ed..fc195c5 100644
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
*************** config_enum_get_options(struct config_en
*** 5055,5061 ****
   *
   * If there is an error (non-existing option, invalid value) then an
   * ereport(ERROR) is thrown *unless* this is called in a context where we
!  * don't want to ereport (currently, startup or SIGHUP config file reread).
   * In that case we write a suitable error message via ereport(LOG) and
   * return false. This is working around the deficiencies in the ereport
   * mechanism, so don't blame me.  In all other cases, the function
--- 5055,5061 ----
   *
   * If there is an error (non-existing option, invalid value) then an
   * ereport(ERROR) is thrown *unless* this is called in a context where we
!  * don't want to ereport (currently, settings defaults and cfg file reading)
   * In that case we write a suitable error message via ereport(LOG) and
   * return false. This is working around the deficiencies in the ereport
   * mechanism, so don't blame me.  In all other cases, the function
*************** set_config_option(const char *name, cons
*** 5074,5080 ****
  	bool		prohibitValueChange = false;
  	bool		makeDefault;
  
! 	if (context == PGC_SIGHUP || source == PGC_S_DEFAULT)
  	{
  		/*
  		 * To avoid cluttering the log, only the postmaster bleats loudly
--- 5074,5080 ----
  	bool		prohibitValueChange = false;
  	bool		makeDefault;
  
! 	if (source == PGC_S_FILE || source == PGC_S_DEFAULT)
  	{
  		/*
  		 * To avoid cluttering the log, only the postmaster bleats loudly
